If I have an array of objects Array 1:[Object 1, Object 2, Object 3] and each object looks like the following:
object 1 has properties : creation date, name, class, size where name = Bear
object 2 has properties : creation date, name, class, size where name = Dog
object 3 has properties : creation date, name, class, size where name = Guerilla
And I want to sort these objects based upon their respective names in alphabetical order, so Array 2 looks like the following [Object 1 (Bear), Object 2 (Dog), Object 3 (Guerilla)]
how would I approach this problem in Javascript? Are there any convenience methods for doing this? I am relatively new to JS. Thank you in advance!
Use the sort method with a custom comparer:
Array1.sort(function(x, y){
var n1 = x.name;
var n2 = y.name;
return n1 == n2 ? 0
: n1 < n2 ? -1
: 1;
});
arr.sort(function (a, b) {
return a.localeCompare(b);
});
Note that sort is an in-place sort, so your original array will be sorted.
The javascript sort method accepts an anonymous comparison function that gives you all the flexibility that you would need to sort objects on any attribute.
The general pattern is:
arr.sort(function(a,b){...});
The "anonymous" function provided to the sort method accepts two objects to compare, and should return a value that indicates which element to sort higher, as follows:
if a should be sorted higher than b, return 1
if a should be sorted lower than b, return -1
if a is equivalent to b (for sorting purposes), return 0
Here's an example (ellipses indicate other attributes):
var beasties = [
{name:'Bear', created_at: ... },
{name:'Dog', ... },
{name:'Gorilla', ... }
];
beasties.sort(function(a,b){return a.name > b.name});
Here, I'm relying on the ability for js to compare the strings that are returned by the name attribute.
I think that ought to do the trick for you.
You can pass a custom compare function to Array.sort which will then be used by the sorting algorithm to decide which one of two array elements is larger. When the algorithm compares two objects, it passes these to the compare function. When the function returns 1, it considers the first one as larger. When it returns -1, it considers the second one larger. When it returns 0, it considers them equal.
function compare_function(obj1, obj2){
if (obj1.name == obj2.name) return 0;
if (obj1.name < obj2.name) return -1 else return 1;
}
my_array.sort(compare_function)
You can use the sort method of the array, and pass in a function:
Array1.sort(function(left,right) {
if (left.name < right.name) return -1;
if (left.name > right.name) return 1;
return 0;
});
Related
As part of the precourse for a coding bootcamp, we have to create a simpler version of the underscore JS library. I am struggling with creating the _.first function, which:
Returns an array with the first n elements of an array.
If n is not provided it returns an array with just the first element.
This is what I've got so far:
_.first = function(array, n) {
if (!Array.isArray(array)) return [];
if (typeof n != "number" || n <= 0) return [].slice.call(array, 0, 1);
return n >= array.length ? array : [].slice.call(array, 0, n);
};
It passes all test except one: "It must work on an arguments object"
I know the arguments object passes an array with all the arguments passed and it has a length property but Im struggling to work with it.
Any help would be much appreciated.
The arguments object is just that, a variable defined implicitly on each function scope that acts like an array. Has a length property and you can access the elements by using number properties like a normal array:
var _ = {};
_.first = function() {
if (arguments.length == 0) { // If there's no arguments
return [];
} else { // When there's 1 or more arguments
var array = arguments[0];
var n = arguments.length > 1 ? arguments[1] : 1; // If there's only the "array" argument ("n" is not provided), set "n" to 1
// And now your code, which has nice checks just in case the values are invalid
if (!Array.isArray(array)) {
return [];
}
if (typeof n != "number" || n <= 0) {
n = 1;
}
return [].slice.call(array, 0, n); // Don't worry if slice is bigger than the array length. It will just work, and also always return a copy of the array instead of the array itself.
}
};
console.log( _.first() );
console.log( _.first([0,1,2]) );
console.log( _.first([0,1,2], 2) );
console.log( _.first([0,1,2], 10) );
I would add something to the first answer. The arguments object is something that is normally created implicitly by JavaScript and made available inside the function body. In order to write a unit test for "It must work on an arguments object", they must explicitly define an arguments object and pass it in. This is a bad unit test because it is testing the internal working of your function. You should be free to write the function any way you like, and a unit test should test the external behaviour of the function (return value and/or side effects, based on the arguments passed).
So imo your original solution is good and the test is designed to force you to use a certain syntax for the sake of learning, but this is misleading.
I want to sort an array objects like so.
var obj = [{"UMAIR":410},
{"ALI":2177},
{"JOHN":410},
{"ANTHENY":410},
{"FRANKLY":410},
{"FRONTY":534},
{"SLIM":534},
{"ASFUND":534}];
I want to sort it with integer values of each object.
I am trying to understand following code (that I have found online):
obj.sort(function(a, b) {
return a.price - b.price;
});
But in this code its using price property, but I dont' have any specific property here.
You can try the sort function...
obj.sort(function(a,b) {
return a[Object.keys(a)[0]] - b[Object.keys(b)[0]];
});
is Equivalent to:
obj.sort(function(a,b) {
var aValue = a[Object.keys(a)[0]];
var bValue = b[Object.keys(b)[0]];
if (aValue > bValue)
return 1;
else if (aValue < bValue)
return -1;
else
return 0;
});
Edit, Just saw your edit, yeah you did find it.
You should also search how to extract elements from json, which in your case is
Object.keys,
It Returns an array with the key strings.
Since your Object contains a SINGLE key, you get from the array the first value (0) and then, you are making the subtraction of values from a to b.
a,b are entries of your array. they are objects.
In this Link you can check how sorting function works
Code from the Link i provided
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;
}
I am trying to sort the array based on one property start of the array objects.
events = _.sortBy(events, function(a) {
return moment(new Date(a.start)).format();
});
This gives me the correct results. However, the following does not.
events = events.sort(function(a, b) {
return moment(new Date(a.start)).format() > moment(new Date(b.start)).format();
});
Does anyone know what is happening?
Fiddle: https://jsfiddle.net/q24zx11h/1/
Compare function must return -1, 0 or 1:
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;
}
Currently your code returns boolean and I think it's parsed to 0 or 1 so your code runs but not correctly.
Comparator functions usually return an integer argument indicating the following values:
-1: a is smaller than b
0: a equals b
1: a is larger than b
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/sort
A handy trick is to subtract the discrete value of a from the discrete value of b, in your case for example by using the timestamp:
function (a, b) { return (new Date(b)).getTime() - (new Date(a)).getTime(); }
If b is now larger than a, it will return a positive value, and so forth.
This is what the docs of Array.sort say:
arr.sort([compareFunction])
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
Your function returns a boolean, which is then cast to a Number, which is 0 or 1, and in this case 0 means equal (as "these elements are the same, put them in whatever order").
I found same results with both your codes
var manualSort = days.sort(function(a, b) {
return moment(new Date(a.start)).format() > moment(new Date(b.start)).format();
});
var underScoreSort = _.sortBy(days, function(a) {
return moment(new Date(a.start)).format();
});
Both the arrays returned same results.
I am trying to sort an array. For instance, given array a (below), I would like to return array b.
I know I can do a.sort(), however, I don't want to sort on the actual array element, but on a property (s for this example) of the array element. How can this be accomplished?
Thank you
var a=[
{s:"ced",o:{obj:1}},
{s:"cde",o:{obj:2}},
{s:"ade",o:{obj:3}},
{s:"bde",o:{obj:4}}
]
var b=[
{s:"ade",o:{obj:3}},
{s:"bde",o:{obj:4}},
{s:"cde",o:{obj:2}},
{s:"ced",o:{obj:1}}
]
Array.prototype.sort accepts an optional parameter: a callback telling it how to sort.
a.sort(function(x,y) {
// do something here
// return -1 if x < y
// return 1 if x > y
// otherwise, return 0
});
So, in your case, it would be:
a.sort(function(x,y) {return x.s == y.s ? 0 : (x.s < y.s ? -1 : 1);});
a.sort(function(a, b){
if(a.s < b.s){
return -1;
}
if(a.s > b.s){
return 1;
}
return 0;
});
http://jsfiddle.net/lbstr/nCKpG/
The sort method accepts a compareFunction parameter, where you can define how to calculate sort order.
As you want to compare strings this function should use localeCompare as suggested here.
One way to create a sorting function which can be quickly adjusted is to generate it via another function. This means you can create sort functions automatically for any property of an object.
Put the two to together and you get..
function genSortFn(prop){
return function(a,b){ return a[prop].localeCompare( b[prop] ); };
}
a.sort( genSortFn('s') );
b.sort( genSortFn('s') );
I have an object array called Persons and would like to sort by one of its members, I am new to javascript prorotype and not sure how to do this. The object looks like this:
[ Object { EntityId=0, Name="Edibert", Number="1234", Value=""}]
[ Object { EntityId=0, Name="Jairo", Number="1234", Value=""}]
So it has a few more items there for that array of object Persons. I know i can access the name by doing something like this.Persons[0].Name. But how can i sort it by Name?.
thank you so much
You can do this without Prototype:
Persons.sort(function(a,b) {
if(a.Name < b.Name) { return -1; }
if(a.Name > b.Name) { return 1; }
return 0;
});
Use any properties of the object you want from within the sort function, so long as you return one of the following values:
(-1) if a is to appear before b in the final array
(1) if a is to appear after b
(0) if the two items being sorted are identical
In reality, any negative or positive number would work as a return value, but -1 and 1 are conventional.