Sorting a multi-dimensional JSON object in Javascript - javascript

I tried finding an answer to this on here, but kept coming up with real simplistic examples, so here goes:
I am pulling a photoset list from Flickr's API, and it needs to be in javascript. Anyhow, their response is unlike most others places the value to sort within a sub-object like so:
"photoset":[
{..."photos":"15", "videos":0, "title":{"_content":"Shocktoberfest 2012"}, "description":{"_content":""}, "needs_interstitial":0, "visibility_can_see_set":1, "count_views":"0", "count_comments":"0", "can_comment":0, "date_create":"1351829136", "date_update":"1351829309"}
...
...
...
]
How can I sort on the title for instance, when the value is within in a sub-object like it is?

You could provide a callback to the Array.sort and return the usual -1, 0, 1 for sorting:
some_response.photoset.sort(function(a, b){
return a.title._content.localeCompare(b.title._content);
});

Not sure either but , I would begin to figure it out with a for/in statement loop...
var photoObjects= {};
for(k in initialObject){
photoObjects[k] = initalObject.photoset[0][k];
console.log(photoObjecs[k]);
}

Javascript allows you to pass a function as parameter to the Arrays sort function,
you could just write a simple helper function to sort an array with object after there titles
var arr = [
{title:"A"},
{title:"F"},
{title:"B"}
];
function sortarr (arr,item) {
arr.sort(function (a,b) {
if (typeof a == "object" && typeof b == "object" ) {
console.log(a[item]);
if ( a[item] < b[item] )
return -1;
if ( a[item] > b[item] )
return 1;
return 0;
}
});
return arr;
}
console.log(JSON.stringify(sortarr(arr,"title")));
Here is an example on jsbin

Related

Sort a JSON array by one field during iteration using JS

I have an array as follows:
var array = {"week1":[{"id":1,"name":"x","mark":"20"},{"id":2,"name":"y","mark":"30"}],"week2":[{"id":1,"name":"x","mark":"40"},{"id":2,"name":"y","mark":"60"},{"id":3,"name":"z","mark":"10"}]}
I want to sort the array by mark field. How can I achieve this?
UPDATE
I used the following function to sort the above array object by mark.
$scope.GetSortOrder = function(prop) {
return function(a, b) {
if (a[prop] > b[prop]) {
return 1;
} else if (a[prop] < b[prop]) {
return -1;
}
return 0;
}
};
array.sort($scope.GetSortOrder("mark"));
But then I get the following error
array.sort is not a function
Desired output
var outPut =
{
"week1":[
{"id":1,"name":"x","mark":"20"},
{"id":2,"name":"y","mark":"30"}
],
"week2":[
{"id":3,"name":"z","mark":"10"},
{"id":1,"name":"x","mark":"40"},
{"id":2,"name":"y","mark":"60"}
]
}
var array is not an array (it's an object), therefore you can't use .sort() on it.
It looks like you want to sort the object's values. If so, you want to fetch the object's values using Object.values(), loop through them, and sort those instead.
var obj = {"week1":[{"id":1,"name":"x","mark":"20"},{"id":2,"name":"y","mark":"30"}],"week2":[{"id":1,"name":"x","mark":"40"},{"id":2,"name":"y","mark":"60"},{"id":3,"name":"z","mark":"10"}]}
Object.values(obj).forEach(arr => arr.sort((a,b) => a.mark-b.mark));
console.log(obj);
If you preferred a method that accepts a property name (like in your example), perhaps this curried approach would work for you.
var obj = {"week1":[{"id":1,"name":"x","mark":"20"},{"id":2,"name":"y","mark":"30"}],"week2":[{"id":1,"name":"x","mark":"40"},{"id":2,"name":"y","mark":"60"},{"id":3,"name":"z","mark":"10"}]}
const sortArrayByProperty = prop => arr => arr.sort((a,b) => a[prop].localeCompare(b[prop]));
Object.values(obj).forEach(sortArrayByProperty("mark"));
console.log(obj);

finding the difference in multiple arrays. using reduce

I am trying to recreate the underscore js function difference using reduce.
Difference takes in multiple arrays and returns all values that are similiar to the first array. so [1,2],[2,3],[1,3] should spit out [1,2,2,1].
I was thinking of looping through each of my subarray(rest) and if the value of my sub elements has an index in my first array then I will push that element onto my accumulator value(which is an empty array).
Some reason I do not get my intended output where I was expecting [1,2,3,2,1,2].
instead I am getting [ [ 1, 2 ], [ 2, 4 ], [ 1, 2 ] ]. Can anyone help me with this rewrite using reduce. Thanks.
function difference(arrays){
var arrayed=Array.prototype.slice.call(arguments);
var first=arrayed[0];
var rest=arrayed.slice(1);
return reduce(first,function(acc,cur){
forEach(rest,function(sub){
if (sub.indexOf(cur)>-1){
acc.push(sub);
}});
return acc;
},[]);
}
console.log(difference([1,2,3],[2,4],[1,2],[4,5]));
i know the way im calling forEach is different but it is because my own version of forEach accepts two arguments.
As for your previous question, you need to call array methods on arrays, not pass them as parameters so not
return reduce(first,function(acc,cur){...})
but
return first.reduce(function(acc,cur){...});
In your function:
var first=arrayed[0];
var rest=arrayed.slice(1);
can be replaced with one step using splice:
var first = arrayed.splice(0, 1)
and use arrayed instead of rest. But there's no need for that anyway. If no accumulator is provided, then the first value is used, so (with some renaming of variables):
function difference(){
var args = Array.prototype.slice.call(arguments);
return args.reduce(function(acc, cur){
cur.forEach(function(value){
if (acc.includes(value)){
acc.push(value);
}
});
return acc;
});
}
console.log(difference([1,2,3],[2,4],[1,2],[4,5]));
Could try this
function difference(arrays){
var arrayed=Array.prototype.slice.call(arguments);
var first=arrayed[0];
var rest=arrayed.slice(1);
return first.concat(rest.reduce(function(acc, cur, curIndex, array){
first.forEach(function(eachEle){
if(cur.indexOf(eachEle) > -1 )
acc.push(cur[cur.indexOf(eachEle)]);
});
return acc;
}, []));
}
console.log(difference([1,2,3],[2,4],[1,2],[4,5]));
Here's a solution :
function difference(arrays){
var arrayed = Array.prototype.slice.call(arguments);
var first = arrayed.splice(0,1)[0]; // edit, thanks robG
var tmp = [];
return arrayed.reduce(function(acc, arr) {
return acc.concat(arr.filter(function(el) {
return first.includes(el);
}));
}, first);
}
console.log(difference([1,2,3],[2,4],[1,2],[4,5]));
Use the javascript reduce method on the 'rest' array, makes the first array be the default value of the accumulator, filter the arrays with the first one and concat the result to your accumulator.
Hope it helps,
best regards

javascript - sort javascript array of objects based on the value

I've got an array of object like this:
{"aid":1,"id":51,"modifier":5},
{"aid":2,"id":51,"modifier":5},
{"aid":3,"id":51,"modifier":2},
{"aid":4,"id":51,"modifier":3},
{"aid":5,"id":51,"modifier":3}
I will add an object {"aid":6,"id":51,"modifier":5} , the array now will look like this:
{"aid":1,"id":51,"modifier":5},
{"aid":2,"id":51,"modifier":5},
{"aid":3,"id":51,"modifier":2},
{"aid":4,"id":51,"modifier":3},
{"aid":5,"id":51,"modifier":3},
{"aid":6,"id":51,"modifier":5}
But i want to know is how i will push the new object {"aid":6,"id":51,"modifier":5} not into the last index of the array, but base on the modifier, that will look like this:
{"aid":1,"id":51,"modifier":5},
{"aid":2,"id":51,"modifier":5},
{"aid":6,"id":51,"modifier":5}
{"aid":3,"id":51,"modifier":2},
{"aid":4,"id":51,"modifier":3},
{"aid":5,"id":51,"modifier":3},
I dont know if it is possible, can somebdy solve this. Thanks
You can pass a custom comparison function to Array.sort
e.g
list.sort(function (a, b) {
if (a.modifier > b.modifier) {
return 1;
}
return -1;
});
I am not sure what the logic behind your search order is, but if you can write a a comparison function you can sort by it.
I notice your Objects seem to be sorted by both modifier and aid. This means you want to sort by multiple properties. Write a comparator like this
function comparator(keys, a, b) {
var k, key, mod = [1, -1], order;
for (k = 0; k < keys.length; ++k) {
key = keys[k].key;
order = !keys[k].descending;
if (b[key] > a[key]) return order ? -1 : 1;
else if (b[key] < a[key]) return order ? 1 : -1;
}
return 0;
}
Now say your Array is called foo, .bind the comparator with your key weightings as you pass it into foo.sort
foo.sort(
comparator.bind(null, [
{key: 'modifier', descending: true},
{key: 'aid'},
])
);

Re-order Json array by key value

I have a contact list that is returned to me in this very long form. It is getting returned Based on order of entry (the field outside the first set of brackets, indented). The problem I'm having is I want it to order alphabetically by displayName. Since that is in it's own array inside of the main one I'm having trouble getting the full array to reorder by it. Can anyone figure this out? Thanks. Oh and it's got to be done in JS.
{
"0":
{"id":1,"rawId":null,"displayName":"Person 1","name":null,"nickname":null,"phoneNumbers":[{"type":"mobile","value":"phonenumb53534r","id":0,"pref":false}],"emails":null,"addresses":null,"ims":null,"organizations":null,"birthday":null,"note":null,"photos":null,"categories":null,"urls":null},
"1":
{"id":2,"rawId":null,"displayName":"Person 2","name":null,"nickname":null,"phoneNumbers":[{"type":"mobile","value":"phonenumber535345","id":0,"pref":false}],"emails":null,"addresses":null,"ims":null,"organizations":null,"birthday":null,"note":null,"photos":null,"categories":null,"urls":null},
"2":
{"id":3,"rawId":null,"displayName":"Person 3","name":null,"nickname":null,"phoneNumbers":[{"type":"mobile","value":"phonenumber47474","id":0,"pref":false}],"emails":null,"addresses":null,"ims":null,"organizations":null,"birthday":null,"note":null,"photos":null,"categories":null,"urls":null}, goes on for a couple hundred rows
Objects in JavaScript are not ordinal by nature. If you have an array, you can work with that. Otherwise, you have to convert the outer part of the object into an array yourself:
var arrayOfObj = [];
for (item in obj) {
if (obj.hasOwnProperty(item)) {
arrayOfObj.push(obj[item]);
}
}
If you can do that before you even get the JSON, so much the better. Once you have that, you can just use the normal array .sort method
arrayOfObj.sort(function (a, b) {
if (a.displayName < b.displayName) {
return -1;
}
else if (a.displayName > b.displayName) {
return 1;
}
return 0;
});
http://jsfiddle.net/ZcM7W/
You'll need to parse that responseText into JSON. But since it's returned as an object literal you'll have to convert it to an array. Then you can sort it with a custom comparator function.
var json = JSON.parse(response),
data = [];
for (key in json) {
data.push(json[key]);
}
data.sort(function (a, b) {
return a.displayName > b.displayName;
});

How to access values of array in javascript

Code:
var testarray = [];
var test1 = "ashutosh";
var test2 = "ashutosh2";
if (test1 != test2) {
testarray.push = "ashutosh3";
testarray.push = "ashutosh4";
alert(testarray.length);
}
if (testarray.length != 1) {
alert(testarray.length);
alert(testarray[testarray.length - 1]);
alert(testarray[testarray.length - 2]);
}
But when all the alerts are showing up undefined. I have no clue why is this happening.
push is a function, not a property, so instead of
testarray.push="ashutosh3";
it's
testarray.push("ashutosh3");
Here's how I'd update that code, FWIW, but I think the only substantive change is doing the push correctly and using >= 2 rather than != 1 in the length check at the end (since otherwise if the array is empty you're looking at entries -1 and -2, which will be undefined):
var testarray = [];
var test1 = "ashutosh";
var test2 = "ashutosh2";
if (test1 !== test2) {
testarray.push("ashutosh3");
testarray.push("ashutosh4");
alert(testarray.length);
}
if(testarray.length >= 2) {
alert(testarray.length);
alert(testarray[testarray.length-1]);
alert(testarray[testarray.length-2]);
}
T.J. Crowder already answer the issue with push but I'm guessing you are new to JavaScript so here are some useful tips I wished knew earlier.
For Each Loops
Instead of writing a standard for loop, you can use a forEach loop.
for( i in testArray ){
console.log( i );
}
Objects
Till hashtables and modules make their appearance to JS, we are left with using arrays. Here is the easiest method I know of to make an object.
var ArrayUtils = {
"print" : function(array) {
console.log(array);
}
}
Since ArrayUtils is an list, you can extend it using either dot or bracket notation
ArrayUtils["size"] = function(array){
return array.length;
}
ArrayUtils.indexOf = function(array, i){
return array[i];
}
Higher-Order Functions
Arrays in JavaScript come with a built-in map, reduce and filter functions. These three functions are highly useful when it comes to writing elegant code.
Map, passes each element in an sequence into a function
testArray.map( function(i){ console.log(i); } );
Reduce, well reduces the array into a single value. In this example i'm calculating the sum of the array
testArray.reduce( function(x,y) { return x+y; } );
Filter, as you could guess removes elements from an array. In JS, .filter() returns a new array
testArray = testArray.filter( function(i) { return ( i > 0 ); } );
I also read that JS has iterator and generator support. They are powerful iteration tools and worth checking out if you are going to heavily use iteration in your code base. I don't so, it's been something I put off as a todo.

Categories