why array.sort not work in javascript? - javascript

I have array of object .I want if i add object in array it should add in sorted way .I used array to sort .but it not sort my array . here is my code
https://jsfiddle.net/8oczc5x5/
var arr = [{
elem: {
text: function() {
return "aa";
}
}
}, {
elem: {
text: function() {
return "yy";
}
}
}];
var obj = {
elem: {
text: function() {
return "bb";
}
}
}
arr.push(obj);
arr.sort()
console.log(arr[1].elem.text())
Expected Out put
"bb"
Actual output
"yy"
..why ? I used sort it should sort my array ?

sort only really works "out-of-the-box" when sorting character data alphabetically. And why would you expect it to call your functions and compare them? That's really dangerous and complicated. However, you can perform your own special sort by passing it a function.
Taken from the docs (compareFunction is the function you're passing in):
If compareFunction is supplied, the array elements are sorted according to the return value of the compare function. If a and b are two elements being compared, then:
If compareFunction(a, b) is less than 0, sort a to a lower index than b, i.e. a comes first.
If compareFunction(a, b) returns 0, leave a and b unchanged with respect to each other, but sorted with respect to all different elements. Note: the ECMAscript standard does not guarantee this behaviour, and thus not all browsers (e.g. Mozilla versions dating back to at least 2003) respect this.
If compareFunction(a, b) is greater than 0, sort b to a lower index than a.
compareFunction(a, b) must always return the same value when given a specific pair of elements a and b as its two arguments. If inconsistent results are returned then the sort order is undefined.
arr.sort(function(a, b) {
// localeCompare does a string comparison that returns -1, 0, or 1
return a.elem.text().localeCompare(b.elem.text());
});

function sortNumber(num1,num2) {return num1 - num2;} var numbs = [5, 17, 29, 48, 4, 21];
var sortnumb = numbs.sort(sortNumber);
alert(sortnumb)

You have to specify how to sort
arr.sort( (a,b) => a.elem.text().localeCompare(b.elem.text() );

Related

Explanation of .sort in JavaScript [duplicate]

How does the following code sort this array to be in numerical order?
var array=[25, 8, 7, 41]
array.sort(function(a,b){
return a - b
})
I know that if the result of the computation is...
Less than 0: "a" is sorted to be a lower index than "b".
Zero: "a" and "b" are considered equal, and no sorting is performed.
Greater than 0: "b" is sorted to be a lower index than "a".
Is the array sort callback function called many times during the course of the sort?
If so, I'd like to know which two numbers are passed into the function each time. I assumed it first took "25"(a) and "8"(b), followed by "7"(a) and "41"(b), so:
25(a) - 8(b) = 17 (greater than zero, so sort "b" to be a lower index than "a"): 8, 25
7(a) - 41(b) = -34 (less than zero, so sort "a" to be a lower index than "b": 7, 41
How are the two sets of numbers then sorted in relation to one another?
Please help a struggling newbie!
Is the array sort callback function called many times during the course of the sort?
Yes
If so, I'd like to know which two numbers are passed into the function each time
You could find out your self with:
array.sort((a,b) => {
console.log(`comparing ${a},${b}`);
return a > b ? 1
: a === b ? 0
: -1;
});
EDIT
This is the output I've got:
25,8
25,7
8,7
25,41
The JavaScript interpreter has some kind of sort algorithm implementation built into it. It calls the comparison function some number of times during the sorting operation. The number of times the comparison function gets called depends on the particular algorithm, the data to be sorted, and the order it is in prior to the sort.
Some sort algorithms perform poorly on already-sorted lists because it causes them to make far more comparisons than in the typical case. Others cope well with pre-sorted lists, but have other cases where they can be "tricked" into performing poorly.
There are many sorting algorithms in common use because no single algorithm is perfect for all purposes. The two most often used for generic sorting are Quicksort and merge sort. Quicksort is often the faster of the two, but merge sort has some nice properties that can make it a better overall choice. Merge sort is stable, while Quicksort is not. Both algorithms are parallelizable, but the way merge sort works makes a parallel implementation more efficient, all else being equal.
Your particular JavaScript interpreter may use one of those algorithms or something else entirely. The ECMAScript standard does not specify which algorithm a conforming implementation must use. It even explicitly disavows the need for stability.
Pairs of values are compared, one pair at a time. The pairs that are compared are an implementation detail--don't assume they will be the same on every browser. The callback can be anything (so you can sort strings or Roman numerals or anything else where you can come up with a function that returns 1,0,-1).
One thing to keep in mind with JavaScript's sort is that it is not guaranteed to be stable.
Deeply Knowledge
If the result is negative a is sorted before b.
If the result is positive b is sorted before a.
If the result is 0 no changes are done with the sort order of the two values.
NOTE:
This code is the view inside of the sort method step by step.
OUTPUT:
let arr = [90, 1, 20, 14, 3, 55];
var sortRes = [];
var copy = arr.slice(); //create duplicate array
var inc = 0; //inc meant increment
copy.sort((a, b) => {
sortRes[inc] = [ a, b, a-b ];
inc += 1;
return a - b;
});
var p = 0;
for (var i = 0; i < inc; i++) {
copy = arr.slice();
copy.sort((a, b) => {
p += 1;
if (p <= i ) {
return a - b;
}
else{
return false;
}
});
p = 0;
console.log(copy +' \t a: '+ sortRes[i][0] +' \tb: '+ sortRes[i][1] +'\tTotal: '+ sortRes[i][2]);
}
To help clarify the behavior of Array#sort and its comparator, consider this naive insertion sort taught in beginning programming courses:
const sort = arr => {
for (let i = 1; i < arr.length; i++) {
for (let j = i; j && arr[j-1] > arr[j]; j--) {
[arr[j], arr[j-1]] = [arr[j-1], arr[j]];
}
}
};
const array = [3, 0, 4, 5, 2, 2, 2, 1, 2, 2, 0];
sort(array);
console.log("" + array);
Ignoring the choice of insertion sort as the algorithm, focus on the hardcoded comparator: arr[j-1] > arr[j]. This has two problems relevant to the discussion:
The > operator is invoked on pairs of array elements but many things you might want to sort such as objects don't respond to > in a reasonable way (the same would be true if we used -).
Even if you are working with numbers, oftentimes you want some other arrangement than the ascending sort that's been baked-in here.
We can fix these problems by adding a comparefn argument which you're familiar with:
const sort = (arr, comparefn) => {
for (let i = 1; i < arr.length; i++) {
for (let j = i; j && comparefn(arr[j-1], arr[j]) > 0; j--) {
[arr[j], arr[j-1]] = [arr[j-1], arr[j]];
}
}
};
const array = [3, 0, 4, 5, 2, 2, 2, 1, 2, 2, 0];
sort(array, (a, b) => a - b);
console.log("" + array);
sort(array, (a, b) => b - a);
console.log("" + array);
const objArray = [{id: "c"}, {id: "a"}, {id: "d"}, {id: "b"}];
sort(objArray, (a, b) => a.id.localeCompare(b.id));
console.log(JSON.stringify(objArray, null, 2));
Now the naive sort routine is generalized. You can see exactly when this callback is invoked, answering your first set of concerns:
Is the array sort callback function called many times during the course of the sort? If so, I'd like to know which two numbers are passed into the function each time
Running the code below shows that, yes, the function is called many times and you can use console.log to see which numbers were passed in:
const sort = (arr, comparefn) => {
for (let i = 1; i < arr.length; i++) {
for (let j = i; j && comparefn(arr[j-1], arr[j]) > 0; j--) {
[arr[j], arr[j-1]] = [arr[j-1], arr[j]];
}
}
};
console.log("on our version:");
const array = [3, 0, 4, 5];
sort(array, (a, b) => console.log(a, b) || (a - b));
console.log("" + array);
console.log("on the builtin:");
console.log("" +
[3, 0, 4, 5].sort((a, b) => console.log(a, b) || (a - b))
);
You ask:
How are the two sets of numbers then sorted in relation to one another?
To be precise with terminology, a and b aren't sets of numbers--they're objects in the array (in your example, they're numbers).
The truth is, it doesn't matter how they're sorted because it's implementation-dependent. Had I used a different sort algorithm than insertion sort, the comparator would probably be invoked on different pairs of numbers, but at the end of the sort call, the invariant that matters to the JS programmer is that the result array is sorted according to the comparator, assuming the comparator returns values that adhere to the contract you stated (< 0 when a < b, 0 when a === b and > 0 when a > b).
In the same sense that I have the freedom to change my sort's implementation as long as I don't breach my specification, implementations of ECMAScript are free to choose the sort implementation within the confines of the language specification, so Array#sort will likely produce different comparator calls on different engines. One would not write code where the logic relies on some particular sequence of comparisons (nor should the comparator produce side effects in the first place).
For example, the V8 engine (at the time of writing) invokes Timsort when the array is larger than some precomputed number of elements and uses a binary insertion sort for small array chunks. However, it used to use quicksort which is unstable and would likely give a different sequence of arguments and calls to the comparator.
Since different sort implementations use the return value of the comparator function differently, this can lead to surprising behavior when the comparator doesn't adhere to the contract. See this thread for an example.
Is the array sort callback function called many times during the course of the sort?
Yes, that's exactly it. The callback is used to compare pairs of elements in the array as necessary to determine what order they should be in. That implementation of the comparison function is not atypical when dealing with a numeric sort. Details in the spec or on some other more readable sites.
Is the array sort callback function called many times during the course of the sort?
Since this is a comparison sort, given N items, the callback function should be invoked on average (N * Lg N) times for a fast sort like Quicksort. If the algorithm used is something like Bubble Sort, then the callback function will be invoked on average (N * N) times.
The minimum number of invocations for a comparison sort is (N-1) and that is only to detect an already sorted list (i.e. early out in Bubble Sort if no swaps occur).
Is the array sort callback function called many times during the course of the sort?
Yes
If so, I'd like to know which two numbers are passed into the function each time.
a: The first element for comparison.
b: The second element for comparison.
In the following example, a will be "2" and b will be "3" in the first iteration
How are the two sets of numbers then sorted in relation to one another?
Elements are sorted according to the return value of the compare function.
greater than 0: sort a after b
less than 0: sort a before b
equal to 0: keep original order of a and b
Here is an example
var arr = [3, 2, 1, 5, 4, 6, 7, 9, 8, 10];
console.log(arr.sort((a, b) => {
console.log(a - b, a, b);
//b-a if sorting in decending order
return a - b;
}));

why sort function in javascript return wrong order

I use sort function in javascript to order array,here is my array
var arr=[1118, 8446, -9046, -1719, 41, 279, 11, 2047, 3855, 4925, 7380, 8477];
arr.sort((a,b) => {return a-b > 0});
but I got the wrong order ,here is the result,
[11, 1118, -9046, -1719, 41, 279, 2047, 3855, 4925, 7380, 8446, 8477]
here is the screenshot.So where am I wrong?
If compareFunction is supplied, the array elements are sorted according to the return value of the compare function. If a and b are two elements being compared, then:
If compareFunction(a, b) is less than 0, sort a to a lower index than b, i.e. a comes first.
If compareFunction(a, b) returns 0, leave a and b unchanged with respect to each other, but sorted with respect to all different elements. Note: the ECMAscript standard does not guarantee this behaviour, and thus not all browsers (e.g. Mozilla versions dating back to at least 2003) respect this.
If compareFunction(a, b) is greater than 0, sort b to a lower index than a.
compareFunction(a, b) must always return the same value when given a specific pair of elements a and b as its two arguments. If inconsistent results are returned then the sort order is undefined.
So, the compare function has the following form:
function compare(a, b) {
if (a is less than b by some ordering criterion) {
return -1;
}
if (a is greater than b by the ordering criterion) {
return 1;
}
// a must be equal to b
return 0;
}
var arr=[1118, 8446, -9046, -1719, 41, 279, 11, 2047, 3855, 4925, 7380, 8477];
arr.sort(function(a, b) {
return a - b; // ascending
});
console.log(arr);
arr.sort(function(a, b) {
return b - a; // descending
});
console.log(arr);

Difference between sort(), sort(function(a,b){return a-b;}); and sort(function(a,b){...})

I am trying to understand how exactly sort() works and how I am supposed to use it.
I did some research (google) and went through the similar questions here on stackoverflow, but there are still a few things not 100% clear to me.
So my understanding so far is the following:
There are:
sort() without parameters: sorts only simple arrays of String values alphabetically and in ascending order
E.g.
// sort alphabetically and ascending:
var myArr=["Bob", "Bully", "Amy"]
myArr.sort() // Array now becomes ["Amy", "Bob", "Bully"]
sort() with a function as a parameter: sorts objects in arrays according to their properties; the items are, however, compared as numbers
myArr.sort(function(a,b) {
return a - b;
});
sort() with a function as a parameter: sorts objects in arrays according to their properties; the items can be numbers or Strings
myArr.sort(function(a, b) {
if (a.sortnumber < b.sortnumber) return -1;
else if (a.sortnumber > b.sortnumber) return 1;
return 0;
});
I tried sorting the following array with all these 3 sort() functions.
var myArr = [{
"sortnumber": 9,
"name": "Bob"
},
{
"sortnumber": 5,
"name": "Alice"
},
{
"sortnumber": 4,
"name": "John"
},
{
"sortnumber": 3,
"name": "James"
},
{
"sortnumber": 7,
"name": "Peter"
},
{
"sortnumber": 6,
"name": "Doug"
},
{
"sortnumber": 2,
"name": "Stacey"
}];
//myArr.sort(); // doesn't do anything since it doesn't know on what property to sort
/*
myArr.sort(function(a, b) {
return (a.sortnumber - b.sortnumber); // sorts array
return (a.name - b.name); // doesn't sort array
});
*/
/*
// sorts array even when I use name as property to sort on
myArr.sort(function(a, b) {
if (a.sortnumber < b.sortnumber) return -1;
else if (a.sortnumber > b.sortnumber) return 1;
return 0;
});
*/
console.log(myArr);
Here is also a fiddle.
So, my questions are:
Is my understanding correct?
Is there anything that I am missing?
If the third case works at all times, can I always stick to it or are
the other two cases more efficient in some way or have any advantages to the
third case?
I would really appreciate it if anyone could elaborate on the above. Thank you.
Ok, so after some additional research, going through the MDN documentation, and the arraysort and arraysort2 links, which I found very helpful, I created a slide that could probably be of use to someone else, so I am posting it here. Thank you all for your answers!
First of all, you did a good research and covered almost all possible cases, and you can find the MDN documentation here
You just missed the case of Sorting non-ASCII characters
For sorting strings with non-ASCII characters, i.e. strings with accented characters (e, é, è, a, ä, etc.), strings from languages other than English: use String.localeCompare. This function can compare those characters so they appear in the right order.
var items = ['réservé', 'premier', 'cliché', 'communiqué', 'café', 'adieu'];
items.sort(function (a, b) {
return a.localeCompare(b);
});
// items is ['adieu', 'café', 'cliché', 'communiqué', 'premier', 'réservé']
According to Array reference (http://www.w3schools.com/jsref/jsref_sort.asp):
By default, the sort() method sorts the values as strings in alphabetical and ascending order.
So your first understanding about sort() is correct. However, the second and third are not yet correct. First of all, they are both the same case, which is providing a sorting function to the sort() method. This method should compare the a and b, and return negative, zero, or positive values, indicating if a is less than, equals, or greater than b. So for example, you can still compare your myArr using the name property like this:
myArr.sort(function(a,b) {
return a.name.localeCompare(b.name);
});
I found this at https://www.w3schools.com/js/js_array_sort.asp in "The Compare Function" section. Hope this helps, thank you :)
The Compare Function: The purpose of the compare function is to define an alternative sort order.
The compare function should return a negative, zero, or positive value, depending on the arguments:
function(a, b){return a - b}
When the sort() function compares two values, it sends the values to the compare function, and sorts the values according to the returned (negative, zero, positive) value.
If the result is negative a is sorted before b.
If the result is positive b is sorted before a.
If the result is 0 no changes are done with the sort order of the two values.
Example:
The compare function compares all the values in the array, two values at a time (a, b).
When comparing 40 and 100, the sort() method calls the compare function(40, 100).
The function calculates 40 - 100 (a - b), and since the result is negative (-60), the sort function will sort 40 as a value lower than 100.
You can use this code snippet to experiment with numerically and alphabetically sorting:
<html>
<body>
<h2>JavaScript Array Sort</h2>
<p>Click the buttons to sort the array alphabetically or numerically.</p>
<button onclick="myFunction1()">Sort Alphabetically</button>
<button onclick="myFunction2()">Sort Numerically</button>
<p id="demo"></p>
<script>
const points = [40, 100, 1, 5, 25, 10];
document.getElementById("demo").innerHTML = points;
function myFunction1() {
points.sort();
document.getElementById("demo").innerHTML = points;
}
function myFunction2() {
points.sort(function(a, b){return a - b});
document.getElementById("demo").innerHTML = points;
}
</script>
</body>
</html>
I think, you would like to combine the sort criteria, like this example which sort by name forst and then by number. Please watch 'John'.
var myArr = [{ "sortnumber": 9, "name": "Bob" }, { "sortnumber": 5, "name": "Alice" }, { "sortnumber": 4, "name": "John" }, { "sortnumber": 3, "name": "James" }, { "sortnumber": 7, "name": "Peter" }, { "sortnumber": 6, "name": "Doug" }, { "sortnumber": 2, "name": "Stacey" }, { "sortnumber": 14, "name": "John" }, { "sortnumber": 12, "name": "John" }];
myArr.sort(function (a, b) {
return a.name.localeCompare(b.name) || a.sortnumber - b.sortnumber;
});
console.log(myArr);
I am validating something with an array in the browser console and suddenly run array.sort() function. Then I got the issue. array.sort() is not working properly for all data types in javascript/typescript. Ya, it's a mystery, I did not validate it during studying time. Ha, it's too fun, but it's interesting.
If we check the "developer.mozilla", they clearly mention it at top. But we didn't point out, how it works.
Array.prototype.sort()
The sort() method sorts the elements of an array in place and returns the reference to the same array, now sorted.
The default sort order is ascending, built upon converting the elements into strings, then comparing their sequences of UTF-16 code units values.
I also got some interesting facts and decided to share them here:
-- It is a great learning for me

How to short on desending order using a object property using parseFloat?

I have the following test code
var arr = [{
EmployeeInfo: [{
annualWage: "24000"
}],
name: "Tim",
surname: "Jones",
id: "1111"
}, {
EmployeeInfo: [{
annualWage: "52000"
}],
name: "Terry",
surname: "Phillips",
id: "2222"
}];
console.log(arr);
arr.sort(function (a, b) {
return parseFloat(a.EmployeeInfo[0].annualWage) - parseFloat(b.EmployeeInfo[0].annualWage);
});
console.log(arr);
I want to sort the array by annualWage with the highest earner at the beginning.
Can't seem to get it to work... what obvious thing am I missing?
You just need to reverse the order. The rules are as follows:
If compareFunction is supplied, the array elements are sorted according to the return value of the compare function. If a and b are two elements being compared, then:
If compareFunction(a, b) is less than 0, sort a to a lower index than b, i.e. a comes first.
If compareFunction(a, b) returns 0, leave a and b unchanged with respect to each other, but sorted with respect to all different
elements. Note: the ECMAscript standard does not guarantee this
behaviour, and thus not all browsers (e.g. Mozilla versions dating
back to at least 2003) respect this.
If compareFunction(a, b) is greater than 0, sort b to a lower index than a.
compareFunction(a, b) must always return the same value when given a specific pair of elements a and b as its two arguments. If
inconsistent results are returned then the sort order is undefined.
So basically:
arr.sort(function(a, b) {
return parseFloat(b.EmployeeInfo[0].annualWage) - parseFloat(a.EmployeeInfo[0].annualWage);
});
You're sorting it backwards and putting the lowest earner at the beginning.
Swap a and b in your compare function.
return parseFloat(b.EmployeeInfo[0].annualWage) - parseFloat(a.EmployeeInfo[0].annualWage);
There you go,
swapped a and b and no need for float
arr.sort(function(a, b) {
return parseInt(b.EmployeeInfo[0].annualWage) - parseInt(a.EmployeeInfo[0].annualWage);
});
here is my solution how im doing sort:
a.sort(function (x, y) { return ((x > y) - (y > x)) * d; });
where d == 1 for ascending sort and d==-1 for descending

Merge and sort an array of numbers in numerical order - javascript

I am trying to merge and sort 2 arrays in numerical order.
function merge_arrays(a, b) {
console.log( (a.concat(b)).sort().join(" ") );
}
This works fine with single digits in an array, but it doesn't sort numbers with double digits properly.
e.g.:
a: [2, 3, 7, 8, 8,]
b: [7, 8, 13]
will output as: 13 2 3 7 7 8 8 8
Am I missing something?
Quoting from MDN:
The default sort order is lexicographic (not numeric).
Try this instead:
function merge_arrays(a, b) {
console.log( (a.concat(b)).sort(function(a, b) { return a - b; }).join(" ") );
}
http://www.w3schools.com/jsref/jsref_sort.asp
See that section
Note: When numbers are sorted alphabetically, "40" comes before "5".
To perform a numeric sort, you must pass a function as an argument when calling the sort method.
The function specifies whether the numbers should be sorted ascending or descending.
Meaning This
function numOrdA(a, b){ return (a-b); }
and your code :
a.concat(b)).sort(numOrdA).join(" ")
Try this:
c = a.concat(b)
c == [2,3,7,8,8,7,8,13]
c.sort() == [13,2,3,7,7,8,8,8]
This is because, when not provided with a comparison function, sort automatically converts the elements of the list it is sorting to strings. In string land "13" < "2".
Check out the sort documentation.
So what you probably want is something like this:
function compare_number(a,b) {
return a - b;
}
a.concat(b).sort(compare_number);
And to fully answer your question:
a.concat(b).sort(compare_int).join(" ");

Categories

Resources