📜 ⬆️ ⬇️

Several useful cases when working with arrays in javascript

Very often on a toaster I see questions like “How to sort an array in JavaScript according to a specific rule?”, “How to do an array in JavaScript <action>?”, Etc.

Under the cat collected some manipulations over the arrays.

Convert an array-like object to an array


A remarkable Array.from function was added to es2015 that can convert everything that looks like an array into an array. The principle of its work is as follows:

  1. If there is a function in the [Symbol.iterator] property in the passed object, it will be used as a generator to fill the array.
  2. If the transmitted object has the length property, then the array will be composed of integer indices of the object from 0 to (object.length - 1)
  3. In other cases, it will return an empty array.

Using:
var arr = Array.from(obj); 

From standard objects, strings are considered as mass-like (they are broken character by character), generators, objects of class Set, arguments, and some other
')

The sum and product of the array


 var arr = [1, 2, 3, 4, 5]; var sum = arr.reduce((a, b) => a + b, 0); // 15 var prod = arr.reduce((a, b) => a * b, 1); // 120 

But with the sum you need to be careful, if the array does not meet a numeric value, then it will be converted to a string, and starting with it concatenation of strings will go to avoid this, you can use a safer option:

 var sum = arr.reduce((a, b) => a + (+b || 0), 0); 

Array search and array filtering


Many people know about such a wonderful method as indexOf, which searches the array for the exact value passed in the first argument (value === element) and returns the index of the first match or -1 if nothing was found. You can also pass the second argument with the index from which to start the search.

There is a similar method lastIndexOf, which works similarly, only the search is performed from the end of the array. But there are situations when searching by exact match is not suitable, for these cases there are methods find and findIndex they work in a similar way, calling for each element a function passed in the first argument with parameters (element, index, array). The search is performed until the function returns true. find returns the found element itself or undefined if nothing is found, and findIndex its index or -1, respectively.

An example, we find in the array the first element that is greater than 5:

 var arr = [1, 4, 2, 8, 2, 9, 7]; var elem = arr.find(e => e > 5); // 8 var index = arr.findIndex(e => e > 5); // 3 

Another common task is filtering an array. For these purposes, there is a filter method that returns a new array consisting of only those elements for which the function passed in the first argument returns true:

 var arr = [1, 4, 2, 8, 2, 9, 7]; var filtredArr = arr.filter(e => e > 5); // [8, 9, 7] 

It is also sometimes necessary to simply check the elements of an array for compliance with some condition; for this, there are some and every methods, like the previous methods they work with the function passed in the first argument:

some returns true if the function returns true for at least one argument, and false otherwise
every returns false, if at least for one argument the function returned false, and true otherwise

Both stop searching when the desired value is found. This can be used somewhat nonstandardly, as is known, the forEach method iterates through all the elements of an array, but its operation cannot be interrupted, however this becomes possible due to the some method:

 var arr = [1, 4, 2, 8, 2, 9, 7]; arr.some(function(element, index) { console.log(index + ': ' + element); if(element === 8) { return true; //  } }); /*   : 0: 1 1: 4 2: 2 3: 8 */ 

Sorting arrays


To sort an array, use the sort method. By default, all elements are sorted as strings by increasing utf-16 codes. Standard behavior can be changed by passing the comparator function as the first argument. A comparator is a function that takes two arguments (a, b) as input and should return: -1 if a is earlier than b; 1 if a comes later than b; 0, if the order is not important, that is, the arguments are equal. The sort method is fairly loyal to the comparator and takes any values ​​less than 0 as -1 on output, and values ​​more than 0 as 1.

Important! The sort method, although it returns a result, conducts all operations on the source array. If you need to leave the original array unchanged, you can use the following technique:

 var sortedArr = arr.slice().sort(); 

Since the slice method with no arguments returns an array clone, the sort method will work with this clone and will return it as a result.

Simple sorting, comparing elements as numbers

 arr.sort((a, b) => a - b); //  arr.sort((a, b) => b - a); //  

Type safe sorting

 arr.sort((a, b) => (a < b && -1) || (a > b && 1) || 0); //  arr.sort((a, b) => (a < b && 1) || (a > b && -1) || 0); //  

Sorting an array of objects by their properties

A more frequent situation arises when you need to sort an array of objects of the same type by their property, or even several properties at once, for this it is convenient to have a function that would create a comparator for any case of life:

 function compare(field, order) { var len = arguments.length; if(len === 0) { return (a, b) => (a < b && -1) || (a > b && 1) || 0; } if(len === 1) { switch(typeof field) { case 'number': return field < 0 ? ((a, b) => (a < b && 1) || (a > b && -1) || 0) : ((a, b) => (a < b && -1) || (a > b && 1) || 0); case 'string': return (a, b) => (a[field] < b[field] && -1) || (a[field] > b[field] && 1) || 0; } } if(len === 2 && typeof order === 'number') { return order < 0 ? ((a, b) => (a[field] < b[field] && 1) || (a[field] > b[field] && -1) || 0) : ((a, b) => (a[field] < b[field] && -1) || (a[field] > b[field] && 1) || 0); } var fields, orders; if(typeof field === 'object') { fields = Object.getOwnPropertyNames(field); orders = fields.map(key => field[key]); len = fields.length; } else { fields = new Array(len); orders = new Array(len); for(let i = len; i--;) { fields[i] = arguments[i]; orders[i] = 1; } } return (a, b) => { for(let i = 0; i < len; i++) { if(a[fields[i]] < b[fields[i]]) return orders[i]; if(a[fields[i]] > b[fields[i]]) return -orders[i]; } return 0; }; } // arr.sort(compare()); //     arr.sort(compare(-1)); //     arr.sort(compare('field')); //   field   arr.sort(compare('field', -1)); //   field   /*     field1     field2,     ,    field3    */ arr.sort(compare('field1', 'field2', 'field3')); /*     field1       field2   */ arr.sort(compare({ field1 : 1, field2 : -1 })); 

Sort by count

Although the sort method works fairly quickly, on very large arrays its speed may not be enough, since there is a sorting method that shows greater performance if 2 conditions are met, namely, the array is large enough (more than 100,000 elements) and there are many repeated values ​​in the array. It is called sorting by counting. I will provide an example of its implementation for sorting an ascending array of numeric elements:

 function sortCounts(arr) { var counts = arr.reduce((result, value) => { if(typeof result[value] === 'undefined') { result[value] = 0; } return ++result[value], result; }, {}); var values = Object.getOwnPropertyNames(counts).sort((a, b) => a - b); var start = 0; for(let value of values) { let end = counts[value] + start; arr.fill(+value, start, end); start = end; } } 

Source: https://habr.com/ru/post/279867/


All Articles