Sort a javascript array of objects by object property - javascript

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') );

Related

How to get the underscore function _.first to work on the arguments objects?

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.

Sort an array of objects by value when the key is dynamic

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;
}

How to sort an array with objects on the second attribute

I have an array like this:
var myarray = [Object { category="21f8b13544364137aa5e67312fc3fe19", order=2}, Object { category="5e6198358e054f8ebf7f2a7ed53d7221", order=8}]
Of course there are more items in my array. And now I try to order it on the second attribute of each object. (the 'order' attribute)
How can I do this the best way in javascript?
Thank you very much!
You can write your own sort compare function:
myarray.sort(function(a,b) {
return a.order - b.order;
});
The compare function should return a negative, zero, or positive value to sort it up/down in the list.
When the sort method compares two values, it sends the values to the compare function, and sorts the values according to the returned (negative, zero, positive) value.
Try like this:
array.sort(function(prev,next){
return prev.order-next.order
})
You can do something like following
myarray.sort(function(a,b){
return a.order-b.order;
})
For reference - https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/sort
Try like this
//ascending order
myarray.sort(function(a,b){
return a.order-b.order;
})
//descending order
myarray.sort(function(a,b){
return b.order-a.order;
})
JSFIDDLE
write your own compare function
function compare(a,b) {
if (a.last_nom < b.last_nom)
return -1;
if (a.last_nom > b.last_nom)
return 1;
return 0;
}
objs.sort(compare);
Source: Sort array of objects by string property value in JavaScript
Try
Myarray.sort(function(x,y)
{
return x.order-y.order
})

The error of my Javascript function which supposed to return the length of an array if an array is given and return zero otherwise

I don't know much programming and I'm learning Javascript for a couple of days now so my question might be very easy, apologize in advance:
The question is:
Create a function named 'arrayCounter' that takes in a parameter which is an array. The function must return the length of an array passed in or 0 if a 'string', 'number' or 'undefined' value is passed in.
And I've done this:
function arrayCounter(i) {
var no = ['string', 'undefined', 'number'];
for (j = 0; j < no.length; j += 1) {
if(typeof(i) === no[j]) {return 0}
}
return i.length
Why my code is wrong?
You should make use of JavaScript's Array.isArray(arg) function, which tells if you some provided argument arg is an array. Using this function, we will check to see if the argument i passed to your function arrayCounter is an array. If it is, we return its length. Otherwise, we return 0, like such:
function arrayCounter(i) {
// if the argument is an array, return its length
if (Array.isArray(i)) {
return i.length;
}
// otherwise, return zero
else {
return 0;
}
};
If you want your code to be slightly less readable but a bit more concise, you can use JavaScript's conditional ternary operator, like such (as alluded to by #adeneo above):
function arrayCounter(i) {
return (Array.isArray(i) ? i.length : 0);
};

Simple sort algorithm for names - Javascript

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;
});

Categories

Resources