Created | ![]() |
Favourites | Opened | Upvotes | Comments |
28. Apr 2020 | 6 | 0 | 432 | 0 | 0 |
Javascript arrays comes with several built-in functions.
Check out how to create a Sort UX with 2 stacked arrows for ascending & descending sort.
The sort() method sorts an array "in place" and also returns it :
var arr1 = ['a', 'c', 'b'];
var arr2 = arr1.sort(); // arr1 & arr2 reference the same array: ['a', 'b', 'c']
var arr3 = [{ name: 'r' }, { name: 't' }, { name: 's' }];
arr3.sort(function(a, b) { // in the first run a is the second element { name: 't' }, and b is the first element { name: 'r' }.
if (a.name < b.name ) { // if the second element, a, is smaller than the first element, b
return -1; // return -1 to move the second element, a, up
else {
return 1; // return 1 to move the first element up
}
});
// Result : [{ name: 'r' }, { name: 's' }, { name: 't' }]
// return a.name < b.name ? -1 : 1 : ascending - moving a up
// return a.name < b.name ? 1 : -1 : descending - moving a down
var arr4 = [2, 10, 6];
arr4.sort(function(a, b) { // in first run a is the second element 10, and b is the first element 2.
return a-b; // first run is 10-2, which is positive and therefore moves the first element, 2, up
});
// Result : [2, 6 10]
// return a-b : ascending
// return b-a : descending
The localeCompare() string method returns a number indicating the sortorder of the given string relative to a reference string using a locale and other options to manipulate the sort algoritm : "givenString".localeCompare("referenceString", locale, options)
Number indicators :
localeCompare sorting examples with most important options :
"2aa".localeCompare("11aa"); // 1 : given string, "2aa", comes last - not what we want.
"2aa".localeCompare("11aa", undefined, { numeric: true }); // -1 : given string, "2aa" comes first - what we want.
"ä".localeCompare("a", "de"); // 1 : given string, "ä", comes last ("de" is german locale).
"ä".localeCompare("a", "de", { sensitivity: 'base'); // 0 : "ä" & "a" are equal - in german "a" is the base letter of "ä".
"A".localeCompare("a"); // 1 : given string, "A", comes last.
"A".localeCompare("a", undefined, { sensitivity: 'base' }); // 0 : "A" & "a" are equal - "A" is reduced to it's base letter "a".
var arr13 = ["(15)", "'14", "13"];
arr13.sort(function (a, b) {
return a.localeCompare(b, undefined, { ignorePunctuation: false });
}); // ["'14", "(15)", "13"] - likely not what we want.
arr13.sort(function (a, b) {
return a.localeCompare(b, undefined, { ignorePunctuation: true});
}); // ["13", "'14", "(15)"] - more likely we want this.
First I will sort an array with prices written in different ways but without floats
var arr5 = [{ price: "30$" }, { price: 5 }, { price: "$2,000" }, { price: "$7" }];
arr5.sort(function(a, b) {
var aComparer = createComparer(a); // be sure the price is a string and remove unwanted punctuation (ignorePunctuation option does not remove '$' & ',' even if it is my understanding that it should)
var bComparer = createComparer(b);
return aComparer.localeCompare(bComparer, undefined, { numeric: true });
function createComparer(obj) {
return obj.price.toString().replace(/\$|,/, ''); // change based on possible punctuation to remove
}
});
// result : [{ price: 5 }, { price: "$7" }, { price: "30$" }, { price: "$2,000" }]
Unfortunately the numeric option for localeCompare cannot handle floats, so if we had the following array [{ price: "7.2dollar" }, { price: "7dollar" }], the above compareFunction would fail. To sort floats, we will need to test if the elements to compare can be parsed as floats and in that case make a numeric comparison (not a string comparison) :
var arr6 = [{ price: "7.2dollar" }, { price: "7dollar" }];
arr6.sort(function(a, b) {
var aComparer = createComparer(a);
var bComparer = createComparer(b);
var aFloat = parseFloat(aComparer);
var bFloat = parseFloat(bComparer);
if (isNaN(aFloat) || isNaN(bFloat)) {
return aComparer.localeCompare(bComparer); // only in very convoluted price strings would it be neccessary to use the numeric option here
}
else {
return aFloat - bFloat; // numeric comparison - ascending
}
function createComparer(obj) {
return obj.price.toString().replace(/\$|,/, '');
}
});
// Result : [{ price: "7dollar" }, { price: "$7.2" }]
Error: "Uncaught TypeError: a.localeCompare is not a function"
This error happens then localeCompare is called upon a non-string, typically like this:
arr7 = ["7", 5];
arr7.sort(function(a, b) {
return a.localeCompare(b, undefined, { numeric: true });
});
// Result : Uncaught TypeError: a.localeCompare is not a function
In the above code, localeComparer is called upon a (5), which is a number not a string - there are no localeCompare method on number.
The typical solution is to ensure that all values compared on are string, eg. like this :
arr7 = ["7", 5];
arr7.sort(function(a, b) {
return a.toString().localeCompare(b.toString(), undefined, { numeric: true });
});
// Result : [5, "7"]
The find method executes the callback function once for each index of the array until the callback returns a truthy value. If so, find immediately returns the value of that element. Otherwise, find returns undefined. (MDN)
var fruits = [{ name: 'apples', quantity: 2}, { name: 'bananas', quantity: 7}, { name: 'cherries', quantity: 5}];
var bananas = fruits.find(function(fruit) {
return fruit.name == 'bananas'; // callback returns false for the first element (apples), but true for the second element (bananas) - then callback returns true, find returns the element on which the callback returned true.
});
if (bananas != 'undefined') { // find() returns undefined (not null) then it could not find any element.
var bananaCount = bananas.quantity;
}
Note that find will return the element, not a boolean.
The findIndex() method returns the index of the first element in the array that satisfies the provided testing function. Otherwise, it returns -1, indicating that no element passed the test. (MDN)
var fruits = [{ name: 'apples', quantity: 2}, { name: 'bananas', quantity: 7}, { name: 'cherries', quantity: 5}];
var indexOfBananas = fruits.findIndex(function(fruit) {
return fruit.name == 'bananas'; // then callback returns true, findIndex returns the index for the element on which the callback returned true.
});
// Result : indexOfBananas = 1