sarpay
12/3/2018 - 1:13 PM

JS Collections

#JS Collections

https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array

Single Dimensional Array

var a = [];            // these are the same
var b = new Array();  // a and b are arrays with length 0
 
var c = ['foo', 'bar'];           // these are the same
var d = new Array('foo', 'bar');  // c and d are arrays with 2 strings
 
/** these are different: **/
var e = new Array(3);   // e.length == 3, e[0] == undefined
var f = [3];            // f.length == 1, f[0] == 3

Two Dimensional Arrays

var items = [[1,2],[3,4],[5,6]];
alert(items[0][0]); // 1
// -- or -- //
var x = new Array(10);
for (var i = 0; i < 10; i++) {
  x[i] = new Array(20);
}
x[5][12] = 3.0;

Find the index position of an item

Just like String.indexOf(), the return is either the index of
the queried object within the array, or else -1 when the object is not found.
you can provide a second optional argument to define where to start searching.

var myArray = ['one', 'two', 3, 'four', 'five'];

console.log(myArray.indexOf('two')); // 1
console.log(myArray.indexOf('four')); // 3
console.log(myArray.indexOf('one', 1)); // -1

Access the last item of an array

var last = myArray[myArray.length - 1]
console.log(last);// five

Loop thru Array items

myArray.forEach(function (item, index, array) {
  console.log(item, index);
});
// one 0
// two 1

Add item to the end of an Array

let myArray = ['one', 'two', 3, 'four', 'five'];
myArray.push("six");
// -- or --
myArray.splice(5, 0, 'six');
// output: ['one', 'two', 3, 'four', 'five', 'six']

Remove item from the end of an array

let myArray = ['one', 'two', 3, 'four', 'five', 'six'];
myArray.pop(); // 'six' is removed from the end
// output: ['one', 'two', 3, 'four', 'five']

Remove item from the front of an Array

let myArray = ['one', 'two', 3, 'four', 'five'];
myArray.shift(); // 'one' is removed from the front
// output: ['two', 3, 'four', 'five']

Add to the front of an Array

let myArray = ['one', 'two', 3, 'four', 'five'];
myArray.unshift("zero") // add 'zero' to the front
// output: ['zero', 'one', 'two', 3, 'four', 'five']

Remove / Replace an item by index position

let myArray = ['one', 'two', 3, 'four', 'five'];

myArray.splice(3, 1, 'three');
// replaces 1 element on the 3rd index.
// output: ['zero', 'one', 'two', 'three', 'four', 'five']

myArray.splice(6, 0, 'six');
// adds 1 element on the 6th index
// output: ['zero', 'one', 'two', 'three, 'four', 'five', 'six']

myArray.splice(6, 1);
// removes 1 item from the 6th index
// output: ['zero', 'one', 'two', 'three, 'four', 'five']

Remove item from array by value

Array.prototype.remove_by_value = function () {
  //*** remove an item from an array with the value of 'xxx' ***//
  //*** usage: names.remove_by_value('xxx'); ***//
  var what, a = arguments, m = a.length, ax;
  while (m && this.length) {
    what = a[--m];
    while ((ax = this.indexOf(what)) !== -1) {
      this.splice(ax, 1);
    }
  }
  return this;
};

Copy/Clone an Array

// Spread Operator  
const shallowCopy = [...myArray];

// Slice Operator
const shallowCopy = myArray.slice();

// Concat
const shallowCopy = [].concat(myArray)

// Array.from()
const shallowCopy = Array.from(myArray);

Convert Object to 2-Dim. Array

// SOLUTION 1
const lunch = {
  sandwich: `turkey`,
  chips: 'Cape Cod'
};
const entries = Object.entries(lunch)
console.log(entries)
// [['sandwich', 'turkey'], ['chips', 'Cape Cod']]

// ___________

// SOLUTION 2
var obj = {"1":5,"2":7,"3":0}
var result = Object.keys(obj).map(function(key) {
  return [Number(key), obj[key]];
});
// output: [[1, 5], [2, 7], [3, 0]]

Convert regular array to JSON object

alert(JSON.stringify({ contacts: contacts }));

Slice

  • Copies elements from an array.
  • Returns them as a new array.
  • Doesn’t change the original array.
  • Starts slicing from … until given index: array.slice (from, until).
  • Slice doesn’t include “until” index parameter (1-based).
  • Can be used both for arrays and strings.
let array = [1, 2, 3, "hello world", 4.12, true];
let newArray = array.slice(0, 3);
// returns => newArray = [1, 2, 3]

Splice

  • Used for adding/removing elements from array
  • Changes the array
  • Returns an array of removed elements
  • For adding elements: array.splice (index, number of elements, element)
  • For removing elements: array.splice (index, number of elements)
  • Can only be used for arrays.
// remove from array
// array.splice(index, number of items);
let array = [1, 2, 3, "hello world", 4.12, true];
array.splice(2); // Every element starting from index 2, will be removed
// returns => array = [1, 2];

let array = [1, 2, 3, "hello world", 4.12, true];
array.splice(2, 1);
// removes 1 item from the 2nd index
// returns => array = [1, 2, "hello world", 4.12, true];

// add to array
// array.splice(index, number of items, item);
let array = [1, 2, 3, "hello world", 4.12, true];
array.splice(0, 0, 'a', 'b');
// returns => array = ['a', 'b', 1, 2, 3, "hello world", 4.12, true]

let array = [1, 2, 3, "hello world", 4.12, true];
array.splice(1, 2, 'c');
// replaces 2 items starting on the 1st index.
// start at index 1 and replace 2 items with 'c'.
// returns => array = [1, 'c', "hello world", 4.12, true]

let array = [1, 2, 3];
array.splice(array.length, 0, 4);
// adds 1 item to the end of array
// returns => array = [1, 2, 3, 4];

Split

  • Divides a string into substrings.
  • Returns them in an array.
  • Takes 2 parameters, both are optional: string.split(separator, limit).
  • Doesn’t change the original string.
  • Can only be used for strings.
let array = [1, 2, 3, "hello world", 4.12, true];

let myString = array.toString();
// returns => myString = '1,2,3,hello world, 4.12, true'

let newArray = myString.split(",", 3);
// returns => newArray = ["1", "2", "3"]

Concat

Concat is used to join two or more arrays together, it returns a new array containing the items of the joined arrays.

var cars = ["BMW", "Mazda"];
var cars1 = ["Honda", "Ford"];
var allCars = cars.concat(cars1);
console.log(allCars); /* prints out ["BMW", "Mazda", "Honda", "Ford"] */

Map

Map, Filter and Reduce are all High Order Functions (HOC) because they take a function as a parameter as you will see.

Map creates a new array with the results of calling a function for each item in the array in the right order. The syntax for map is:

array.map(function(item, index))
  • item is required, it’s the items that are already in the array.
  • index is optional to use, it’s the index of the current item in the array.
  • arr is also optional, it’s the array object the current element belongs to.

Sample 1

const numbers = [1, 4, 6, 9]
const byTwo = numbers.map(x => x * 2)
// byTwo = [2, 8, 12, 18]

Sample 2

var cars = ["BMW", "Mazda"];
var carsRanked = cars.map((car, i) => i + ": " + car);
// carsRanked = ["0: BMW", "1: Mazda"]

/* same as the one above */
var redCars = cars.map(function(car, i) {
    return i + ": " + car;
});

Sample 3

// convert object to an array of objects.
const peopleObj = {
  jim: {
    name: "jim",
    age: 20
  },
  tim: {
    name: "tim",
    age: 22
  }
}

const objKeysArray = Object.keys(peopleObj);
const peopleArray = objKeysArray.map(i => peopleObj[i]);

Find Value

var array1 = [5, 12, 8, 130, 44];

var foundValue = array1.find(x => x === 12);
// -- or --
var foundValue = array1.find(function(e) {
  return e > 10;
});

// both returns foundValue = 12

Find Index

var array1 = [5, 12, 8, 130, 44];

var foundIndex = array1.findIndex(x => x === 12);
// -- or --
var foundIndex = array1.findIndex(function(e) {
  return e > 10;
});

// both returns foundIndex = 1

Find Array in Array

Lodash

export class UserRoleDto {
    roleId!: number | undefined;
    roleName!: string | undefined;
    roleDisplayName!: string | undefined;
    isAssigned!: boolean | undefined;
    inheritedFromOrganizationUnit!: boolean | undefined;
}

roles: UserRoleDto[];

checkShowEmailPreferencesTab(): boolean {
  let assignedRoleNames =
    _.map(
      _.filter(
        this.roles,
        { isAssigned: true, inheritedFromOrganizationUnit: false }
      ),
      role => role.roleDisplayName
    );
  
  const checkNames = ['Admin', 'Program Manager', 'Origin Manager'];

  this.showEmailPreferencesTab = 
      assignedRoleNames.findIndex(assignedName => 
          assignedName === checkNames.find(checkName => checkName === assignedName.trim())
      ) >= 0;

  return this.showEmailPreferencesTab;
}

Array to String

var elements = ['Fire', 'Wind', 'Rain'];

console.log(elements.join());
// expected output: Fire,Wind,Rain

console.log(elements.join(''));
// expected output: FireWindRain

console.log(elements.join('-'));
// expected output: Fire-Wind-Rain

Map Json Obj. to Array

var list = new Array();
jsonObj.map(function(x) {
  list.push( { id: x.code, text: x.text });
}); 

Filter

Sample 1

const numbers = [1, 2, 5, 6, 8, 9, 13, 42, 65]
let even = numbers.filter(x => x % 2 === 0)
// even = [2, 6, 8, 42]

Sample 2

const array = [1, 2, 1, 3, 2, 2];
var results = [];
array.filter((item, index) => {
  var item = {
    "item": item,
    "index": index,
    "indexOf": array.indexOf(item),
    "duplicate": array.indexOf(item) !== index
  }
  results.push(item);
});
console.table(results);

to display only the "item" column, use:

console.table(results, ["item"]);

Sample 3

const arr1 = [1, 2, 3];
const arr2 = [1, 2, 3];
const arraysHaveSameData = arr1.filter(e => arr2.indexOf(e) < 0).length === 0;
console.log(arraysHaveSameData);
// => returns true;

Reduce

The reduce method is used to reduce the elements of the array and combine them into a final array based on some reducer function that you pass.

Sample 1

const items = ['banana', 'orange', 'banana', 'apple', 'grapes', 'orange', 'apple', 
               'banana', 'peach', 'apple']
let count = items.reduce((acc, curr) => {
  if (acc[curr]) {
    acc[curr]++
  } else {
    acc[curr] = 1
  }
  return acc
}, {})
// count = {banana: 3, orange: 2, apple: 3, grapes: 1, peach: 1}

Sample 2

const array = [1, 2, 1, 3, 2, 2];

var uniquesArray = array.reduce((newArray, item) => {
    var itemExists = newArray.includes(item);
    let uniquesArray = itemExists ? newArray : [...newArray, item];
    return uniquesArray
}, []); // [] is the initial value of the new array

console.log(uniquesArray);
// outputs: [1, 2, 3]

Sample 3

const euros = [29.76, 41.85, 46.5];
const sum = euros.reduce((total, amount) => total + amount); 
// sum = 118.11

Sample 4

const euros = [29.76, 41.85, 46.5];
const average = euros.reduce((total, amount, index, array) => {
  total += amount;
  if (index === array.length-1) { 
    return total/array.length;
  } else { 
    return total;
  }
});
average // 39.37

Sample 5

const euro = [29.76, 41.85, 46.5];
const above30 = euro.reduce((total, amount) => {
  if (amount > 30) {
    total.push(amount);
  }
  return total;
}, []);
// above30 : [ 41.85, 46.5 ]

Sample 6

const fruitBasket = ['banana', 'cherry', 'orange', 'apple', 'cherry', 'orange', 
                     'apple', 'banana', 'cherry', 'orange', 'fig' ];

fruitBasket.reduce((tally, fruit) => {
  if (!tally[fruit]) {
    tally[fruit] = 1;
  } else {
    tally[fruit] = tally[fruit] + 1;
  }
  return tally;
}, {});
// tally = { banana: 2, cherry: 3, orange: 3, apple: 2, fig: 1 }

Sample 7

Flattens an array of arrays;

const data = [[1, 2, 3], [4, 5, 6], [7, 8, 9]];
const flat = data.reduce((total, amount) => {
  return total.concat(amount);
}, []);
// flat : [ 1, 2, 3, 4, 5, 6, 7, 8, 9 ]

Sample 8

const data = [
  {a: 'happy', b: 'robin', c: ['blue','green']}, 
  {a: 'tired', b: 'panther', c: ['green','black','orange','blue']}, 
  {a: 'sad', b: 'goldfish', c: ['green','red']}
];

const colors = data.reduce((total, amount) => {
  amount.c.forEach( color => {
      total.push(color);
  })
  return total;
}, [])
// colors : ['blue','green','green','black','orange','blue','green','red']

const uniqueColors = data.reduce((total, amount) => {
  amount.c.forEach( color => {
    if (total.indexOf(color) === -1){
     total.push(color);
    }
  });
  return total;
}, []);
// uniqueColors : [ 'blue', 'red', 'green', 'black', 'orange']

Chaining

Each one of those functions returns a new array instead of modifying the existing one. Therefore we can use them one after the other and the next one will always return the result from the previous operation.

const numbers = [1, 2, 4, 5, 6, 7, 7, 9, 11, 14, 43, 56, 89]

function isEven(x) {
  return x % 2 === 0
}

function byTwo(x) {
  return x * 2
}

const result = numbers.filter(isEven).map(byTwo)
// [4, 8, 12, 28, 112]

Remove Duplicates from an Array

const array = [1, 2, 1, 3, 2, 2];

Method 1

Set is a new data object introduced in ES6. Because Set only lets you store unique values.
When you pass in an array, it will remove any duplicate values.

const uniqueSet = new Set(array);
// Set: { 1, 2, 3 }

const backToArray = [...uniqueSet];
// -- or --
const backToArray = Array.from(new Set(array));
// [1, 2, 3];

Method 2 - Retrieve the duplicates

const array = [1, 2, 1, 3, 2, 2];
var results = [];
array.filter((item, index) => {
  var item = {
    "item": item,
    "index": index,
    "indexOf": array.indexOf(item),
    "duplicate": array.indexOf(item) !== index
  }
  results.push(item);
});
console.table(results);

to display only the "item" column, use:

console.table(results, ["item"]);

Method 3

const array = [1, 2, 1, 3, 2, 2];

var uniquesArray = array.reduce((newArray, item) => {
    var itemExists = newArray.includes(item);
    let uniquesArray = itemExists ? newArray : [...newArray, item];
    return uniquesArray
}, []); // [] is the initial value of the new array

console.log(uniquesArray);
// outputs: [1, 2, 3]

SETS

https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Set#Methods

https://medium.com/@bretcameron/how-to-make-your-code-faster-using-javascript-sets-b432457a4a77

const set1 = new Set([1, 2, 3, 4, 5]);

console.log(set1.has(1));
// expected output: true

console.log(set1.has(5));
// expected output: true

console.log(set1.has(6));
// expected output: false

console.log(set1.size);
// expected output: 5

var o = {a: 1, b: 2};
set1.add(o);
set1.add('some text');
set1.add(99);

set1.delete(5); // removes 5 from the set

// iterate over items in set
// logs the items in the order: 1, "some text", {"a": 1, "b": 2}, {"a": 1, "b": 2} 
for (let item of mySet) console.log(item);

// logs the items in the order: 1, "some text", {"a": 1, "b": 2}, {"a": 1, "b": 2} 
for (let item of mySet.keys()) console.log(item);
 
// logs the items in the order: 1, "some text", {"a": 1, "b": 2}, {"a": 1, "b": 2} 
for (let item of mySet.values()) console.log(item);

// logs the items in the order: 1, "some text", {"a": 1, "b": 2}, {"a": 1, "b": 2} 
//(key and value are the same here)
for (let [key, value] of mySet.entries()) console.log(key);

// convert Set object to an Array object, with Array.from
var myArr = Array.from(mySet); // [1, "some text", {"a": 1, "b": 2}, {"a": 1, "b": 2}]

// the following will also work if run in an HTML document
mySet.add(document.body);
mySet.has(document.querySelector('body')); // true

// converting between Set and Array
mySet2 = new Set([1, 2, 3, 4]);
mySet2.size; // 4
[...mySet2]; // [1, 2, 3, 4]

// intersect can be simulated via 
var intersection = new Set([...set1].filter(x => set2.has(x)));

// difference can be simulated via
var difference = new Set([...set1].filter(x => !set2.has(x)));

// Iterate set entries with forEach
mySet.forEach(function(value) {
  console.log(value);
});

// 1
// 2
// 3
// 4

Relation with Array objects

var myArray = ['value1', 'value2', 'value3'];

// Use the regular Set constructor to transform an Array into a Set
var mySet = new Set(myArray);

mySet.has('value1'); // returns true

// Use the spread operator to transform a set into an Array.
console.log([...mySet]); // Will show you exactly the same Array as myArray

Remove duplicate elements from the array

// Use to remove duplicate elements from the array 
const numbers = [2,3,4,4,2,3,3,4,4,5,5,6,6,7,5,32,3,4,5]
console.log([...new Set(numbers)]) 
// [2, 3, 4, 5, 6, 7, 32]

Relation with Strings

var text = 'India';

var mySet = new Set(text);  // Set ['I', 'n', 'd', 'i', 'a']
mySet.size;  // 5

How are Sets are different from Arrays?

The most fundamental difference is that arrays are an indexed collection. That means the value of data in an array is ordered by the index.

By contrast, Sets are a keyed collection. Instead of using indices, Sets order their data using keys. A Set’s elements are iterable in the order of insertion, and it cannot contain any duplicate data. In other words, every item in a Set must be unique.

What are the main benefits?

In a direct comparison, Sets have several advantages over arrays, especially when it comes to a faster run-time:

  • Search for an Item: Using indexOf() or includes() to check whether an item exists in an array is slow.

  • Deleting an Item: In a Set, you can delete an item by its value. In an array, the equivalent is using splice() based on an element’s index. As in the previous point, depending on indices is slow.

  • Insert an Item: It is faster to add an item to a Set than to add an item to an array using push(), unshift() or an equivalent method.

  • Storing NaN: You cannot use indexOf() or includes() to find the value NaN, while a Set is able to store this value.

  • Removing Duplicates: Set objects only store unique values. If you want to avoid storing duplicates, this is a significant advantage over arrays, where additional code would be required to deal with duplicates.