Assuming only one element in the inner arrays, you could take this element for accessing the property
var array = [[{ ipo: 10 }], [{ ipo: 5 }], [{ ipo: 15 }]];
array.sort(function(a, b) {
return a[0].ipo - b[0].ipo;
});
console.log(array);
.as-console-wrapper { max-height: 100% !important; top: 0; }
Answer from Nina Scholz on Stack OverflowAssuming only one element in the inner arrays, you could take this element for accessing the property
var array = [[{ ipo: 10 }], [{ ipo: 5 }], [{ ipo: 15 }]];
array.sort(function(a, b) {
return a[0].ipo - b[0].ipo;
});
console.log(array);
.as-console-wrapper { max-height: 100% !important; top: 0; }
It does not work because there is an b.ipo does not exist. You can use b[0].ipo then compare it, eg:
var array = [ [ { ipo: 10 } ], [ { ipo: 5 } ], [ { ipo: 15 } ], ];
array.sort(function(a, b) {
return a[0].ipo > b[0].ipo;
});
console.log(array);
Does this do what you want?
//var inboxMessages = {... your input ...};
function convertToOrderedArrays(inboxMessages) {
var output = [];
var thread_ids = Object.keys(inboxMessages);
var threadObject, threadArray, keys;
for (var ii=0, thread_id; thread_id=thread_ids[ii]; ii++) {
threadObject = inboxMessages[thread_id];
keys = Object.keys(threadObject);
threadArray = [];
output.push(threadArray);
for (var jj=0, key; key=keys[jj]; jj++) {
threadArray.push(threadObject[key]);
}
threadArray.sort(function (a, b) {
return (b.datetime - a.datetime);
});
}
output.sort(function (a, b) {
return(b[0].datetime - a[0].datetime);
});
return output;
}
function getThreadIdArray(threadArrays) {
var thread_id_array = [];
for (var ii=0, thread_array; thread_array=threadArrays[ii]; ii++) {
thread_id = thread_array[0].thread_id;
thread_id_array.push(thread_id);
}
return thread_id_array;
}
function findThreadArray(thread_id, thread_id_array, threadArrays) {
var index = thread_id_array.indexOf(thread_id);
var threadArray;
if (index < 0) {
// no matching thread was found
} else {
threadArray = threadArrays[index];
}
return threadArray;
}
var output = convertToOrderedArrays(inboxMessages);
var thread_id_array = getThreadIdArray(output);
var mostRecentThread = thread_id_array[0];
var mostRecentMessage = output[0][0];
var thread105775 = findThreadArray(105775, thread_id_array, output);
console.log(output);
// sorted array of sorted arrays
console.log(thread_id_array);
// [378552, 224199, 105775, 107917]
console.log(mostRecentThread);
// 378552
console.log(mostRecentMessage);
/* {
created_at: "May 29, 2015"
, datetime: 1432906923
, id: 108
, message: "hi"
, sender_id: 14
, thread_id: 378552
} */
console.log(thread105775);
// sorted array
This array is already sorting from server script of PHP But when i get it from ajax and convert JSON to array then ONLY chrome web browser sort it in numeric thread_id in ascending order.
So now I'm add _ before thread_id from server side to key as _378552 is now string so no sort by CHROME.
And after all i remove _ from thread_id while accessing it.. so my problem solved. This is only problem in chrome browser.
You can try this method of sorting, yes it's a custom sort function, but they're great.
You get the values, in your case the z value, and keeps a list of the indices of each point, then sorts it by z.
Taken from: https://developer.mozilla.org/en-US/docs/JavaScript/Reference/Global_Objects/Array/sort#Example.3A_Sorting_maps
// the array to be sorted var list = ["Delta", "alpha", "CHARLIE", "bravo"]; // temporary holder of position and sort-value var map = []; // container for the resulting order var result = []; // walk original array to map values and positions for (var i=0, length = list.length; i < length; i++) { map.push({ // remember the index within the original array index: i, // evaluate the value to sort value: list[i].toLowerCase() }); } // sorting the map containing the reduced values map.sort(function(a, b) { return a.value > b.value ? 1 : -1; }); // copy values in right order for (var i=0, length = map.length; i < length; i++) { result.push(list[map[i].index]); } // print sorted list print(result);
This should get you started.
(corresponding jsBin is here : http://jsbin.com/olegoj/1/edit )
// 3D points array.
var points=[];
var Vector=function(x,y,z) {
this.x=x;
this.y=y;
this.z=z;
};
Vector.prototype.toString= function() {
return (' x: ' + this.x + ' y: ' + this.y + ' z : ' + this.z);
};
// returns a new vector translatedfrom ampVec * random
Vector.prototype.createRandomShift= function(ampVec) {
var thisRandom = Math.random()*0.9+0.1;
return new Vector(
thisRandom*ampVec.x+this.x,
thisRandom*ampVec.y+this.y,
thisRandom*ampVec.z+this.z );
};
var pointCount=20;
var pt = new Vector(Math.random()*100|0, Math.random()*100|0, Math.random()*100|0 );
var ampVec = new Vector(Math.random()*4-2, Math.random()*4-2, Math.random()*4 - 2);
var ampVecAmp = new Vector(Math.random()*2-1, Math.random()*2-1, Math.random()*2-1) ;
// fill the point array.
// based on the current point shifted randomly by ampVec
// ampVec itself is shifted randomly by ampVecAmp
for(var i=0; i<pointCount; i++) {
points.push(pt );
pt=pt.createRandomShift(ampVec);
ampVec=ampVec.createRandomShift(ampVecAmp);
}
// array of face. a face is an array of 3 point indexes.
var facelist=[];
var faceCount=10, i=faceCount;
// fill the face array
while(i--) {
var thisFacePoints=[];
var ip1 = 0;
// 3 point indexes
thisFacePoints.push(ip1=Math.random()*pointCount|0);
thisFacePoints.push(Math.random()*pointCount|0);
thisFacePoints.push(Math.random()*pointCount|0);
facelist.push(thisFacePoints);
}
// returns the min z for a face
var minZ=function(f) {
return Math.min(f[0].z, Math.min(f[1].z, f[2].z));
};
// returns the max z for a face
var maxZ=function(f) {
return Math.max(f[0].z, Math.max(f[1].z, f[2].z));
};
// !!! sort the faces on Z !!!
facelist.sort(function(a,b) {
if (maxZ(a) < minZ (b)) return 1; // a fully below b
if (minZ(b) < minZ(a) ) return -1; // b fully below a
// !!!!!!!!!!!!!!!!!!!!!!!!
// in fact here is the tricky part :
// here a and b overlap in Z.
return trickyFaceZSort(a,b);
});
// !!!!!! returns wether face a is < to face b when looking at Z (0,0,1).
//Required : a and b overlaps by Z.
var trickyFaceZSort= function(a,b) {
// do some checks on projected(xi), projected(yi) -> return 0 if no overlap
// then you have the hardest part ahead : x,y and z overlap.
return 0;
};
// Print sorted faces
for(var i=0; i<facelist.length; i++) {
var fp=facelist[i];
console.log(' *** face ' + i + ' *** ');
console.log(' ** point 0 ' + points[fp[0]] + ' *** ');
console.log(' ** point 1 ' + points[fp[1]] + ' *** ');
console.log(' ** point 2 ' + points[fp[2]] + ' *** ');
}
LIST is NOT a three dimensional array in Javascript, it is just an array.
//declare an array which names LIST.
var LIST = [];
//set a property named 'C' of the LIST to be an array.
LIST['C']=[];
//set a property named 'B' of the LIST to be an array.
LIST['B']=[];
//set a property named 'cc' of the 'LIST.C'(which is an array object)
LIST['C']['cc']=[];
//set a property named 'bb' of the 'LIST.B'(which is an array object)
LIST['B']['bb']=[];
The fact is you only need to let the last level to be an array, see my example code below.
function iterateOrderd(obj) {
if (obj instanceof Array) {
obj.sort();
for (var j = 0, l=obj.length; j < l; j++) {
console.log(obj[j]);
}
} else {
var sortable = [];
for (var i in obj) {
if (obj.hasOwnProperty(i)) {
sortable.push(i);
}
}
sortable.sort();
for (var j = 0, l=sortable.length; j < l; j++) {
console.log(sortable[j]);
iterateOrderd(obj[sortable[j]]);
}
}
}
var LIST = {};
LIST['C'] = {};
LIST['B'] = {};
LIST['C']['cc']=[];
LIST['B']['bb']=[];
LIST['C']['cc'].push('cc0');
LIST['C']['cc'].push('cc1');
LIST['C']['cc'].push('cc2');
LIST['B']['bb'].push('bb0');
LIST['B']['bb'].push('bb1');
LIST['B']['bb'].push('bb2');
iterateOrderd(LIST);
You need to know that Array inherits from Object.
In JavaScript, any Object instance is an associative array(!), so acts like an Array in PHP. For example:
var o = {}; // or new Object();
o['foo'] = 'bar';
o[0] = 'baz';
for (i in o) { console.log(i, o[i]); }
Sorting an Object does not make much sense. indexOf would kinda work in theory, but is not implemented.
Arrays are ordered lists. Array instances have push(), length, indexOf(), sort() etc., but those only work for numerical indexes. But again, Array inherits from Object, so any array can also contain non-numerical index entries:
var a = []; // or new Array();
a[0] = 'foo'; // a.length is now 1
a.push('baz'); // a[1] === 'baz'
a.qux = 1; // will not affect a.length
a.sort(); // will not affect a.qux
for (i in a) { console.log(i, a[i]); }
I recommend playing around with arrays and objects, and you'll soon get the point.
var items = [
{ name: 'foo-1', featured: true, createdAt: 1493000001 },
{ name: null, featured: false, createdAt: 1493000003 },
{ name: 'foo-3', featured: true, createdAt: 1493000002 },
{ name: 'foo-4', featured: false, createdAt: 1493000004 },
{ name: 'foo-5', featured: false, createdAt: 1493000005 },
];
items.sort(function(a, b) {
if(a.featured && !b.featured) return -1; // if a is featured and b is not, then put a above b
if(!a.featured && b.featured) return 1; // if b is featured and a is not, then put b above a
if(!a.name && b.name) return -1; // if a doesn't have a name and b does, then put a above b
if(a.name && !b.name) return 1; // if b doesn't have a name and a does, then put b above a
return b.createdAt - a.createdAt; // otherwise (a and b have simillar properties), then sort by createdAt descendently
});
console.log(items);
You can use a compare function which can be passed as an argument to the sort() function - see Array.prototype.sort() for more detailed information. In your case the compare function may look like this:
var items = [
{ name: 'foo-1', featured: true, createdAt: 1493000001 },
{ name: null, featured: false, createdAt: 1493000003 },
{ name: 'foo-3', featured: true, createdAt: 1493000002 },
{ name: 'foo-4', featured: false, createdAt: 1493000004 },
{ name: 'foo-5', featured: false, createdAt: 1493000005 },
];
function compare(a, b) {
if (a.featured === true && b.featured === false) return -1;
if (a.featured === false && b.featured === true) return 1;
if (a.name === null && b.featured !== null) return -1;
if (a.name !== null && b.name === null) return 1;
return b.createdAt - a.createdAt;
};
items.sort(compare);
It should cover the case when the name is an empty string.
This isn't sorting, it's making different groups of elements.
Use a forEach loop and push the object onto a different array depending on the condition.
function groupByFavorites(array) {
let result = {
none: [],
one: [],
multiple: []
};
array.forEach(o => {
if (!o.favorites) { // undefined or empty
result.none.push(o);
} else if (o.favorites.length == 1) {
result.one.push(o);
} else {
result.multiple.push(o);
}
return result;
});
}
You can assign a number to each case, with the cases that should come first having lower numbers and then subtract the two when comparing.
function sortBy() {
const getOrder = ({favorites})=>favorites?.length === 1 ? 0 : !favorites?.length ? 1 : 2;
const cmp = (a, b) => (getOrder(a) - getOrder(b));
return list => list.sort(cmp);
}
const data = [{ rentalName: "Foo", favorites:[{}, {}, {}] }, { rentalName: "Bar", favorites:[{}] }, { rentalName: "Baz", favoriteslikes:[{}] }, { Name: "Plugh", favorites:[] }];
const sortByLikes = sortBy();
console.log(sortByLikes(data));
You could compute an array of the differences and find the first non-zero value:
arr.sort((arr1, arr2) => {
let diff = arr1.map((el, index) => el - arr2[index]);
return diff.find(el => el !== 0);
});
Just loop through biggest length of the inner lists, assuming 0 if no value present:
function sortMulti(a, b) {
for (var index = 0; index < Math.max(a.length, b.length); index++) {
var A = (a[index] === void 0) ? 0 : a[index];
var B = (b[index] === void 0) ? 0 : b[index];
var cmp = B - A;
if (cmp != 0) {
return cmp;
}
}
return 0;
}
//TEST
var lista = [
[1, 20],
[2, 4],
[2, 5],
[1, 1],
[0, 9],
[2, 2, 5],
[1, 3]
];
var listb = [
[0, 9],
[1, 1],
[1, 2],
[2, 4],
[2, 5]
];
var output = document.body.appendChild(document.createElement("pre"));
output.innerHTML = "Sorting multidimensionals:\nRAW:\nList a: [" + JSON.stringify(lista.join("],["), null, 1) + "]\nList b: [" + JSON.stringify(listb.join("],["), null, 1) + "]\nSORTED (biggest to smallest):\nList a: [" + JSON.stringify(lista.sort(sortMulti).join("],["), null, 1) + "]\nList b: [" + JSON.stringify(listb.sort(sortMulti).join("],["), null, 1) + "]";
EDIT 1 - Version 2.0
Here is a version that uphold the rules edited into the question:
function sortMulti(a, b) {
for (var outerIndex = 0; outerIndex < Math.max(a.length, b.length); outerIndex++) {
var A = (a[outerIndex] === void 0 ? [0, 0] : a[outerIndex]);
var B = (b[outerIndex] === void 0 ? [0, 0] : b[outerIndex]);
for (var innerIndex = 0; innerIndex < Math.max(A.length, B.length); innerIndex++) {
var cmp = (A[innerIndex] === void 0 ? 0 : A[innerIndex] - B[innerIndex] === void 0 ? 0 : B[innerIndex]);
if (cmp !== 0) {
return cmp;
}
}
}
return 0;
}
//TEST
var list = [
[[21, 5], [16, 18]],
[[12, 45], [15, 23]],
[[12, 45], [15, 22]]
];
var output = document.body.appendChild(document.createElement("pre"));
output.innerHTML = "RAW\n" + JSON.stringify(list.sort(sortMulti).map(function (a) { return JSON.stringify(a); }), null, 2) + "\nSORTED\n" + JSON.stringify(list.sort(sortMulti).map(function (a) { return JSON.stringify(a); }), null, 2) + "\n";
Just return the first non-zero compare value.
I've also made sure anything that's not a number would be sorted last, but if you are certain that you will only get a valid number or null then you can simplify the checks.
const employees = [
{name: 'Ana', salary: null, bonus: 3000},
{name: 'Ana', salary: 80000, bonus: 3000},
{name: 'Ana', salary: 70000, bonus: 3000},
{name: 'Ana', salary: 70000, bonus: 1000}
];
employees.sort((a, b) => {
return a.name.localeCompare(b.name) ||
safeNumCompare(a.salary, b.salary) ||
safeNumCompare(a.bonus, b.bonus);
});
console.log(employees);
function safeNumCompare(a, b) {
const aValid = isValidNum(a), bValid = isValidNum(b);
if (!(aValid || bValid)) return 0;
if (!aValid) return 1;
if (!bValid) return -1;
return a - b;
}
function isValidNum(num) {
return typeof num === 'number' && !isNaN(num);
}
There is an npm package called lodash. You can achieve your required functionality with their sortBy method.
const _ = require('lodash');
let employees = [
{name: 'John', salary: 90000, bonus: 1000},
{name: 'David', salary: 90000, bonus: 1200},
{name: 'Ana', salary: 80000, bonus: 3000}
];
const sortedArray = _.sortBy(employees, ['name', 'salary', 'bonus']);
I hope it helps.
It's this simple:
var a = [[12, 'AAA'], [58, 'BBB'], [28, 'CCC'],[18, 'DDD']];
a.sort(sortFunction);
function sortFunction(a, b) {
if (a[0] === b[0]) {
return 0;
}
else {
return (a[0] < b[0]) ? -1 : 1;
}
}
I invite you to read the documentation.
If you want to sort by the second column, you can do this:
a.sort(compareSecondColumn);
function compareSecondColumn(a, b) {
if (a[1] === b[1]) {
return 0;
}
else {
return (a[1] < b[1]) ? -1 : 1;
}
}
The best approach would be to use the following, as there may be repetitive values in the first column.
var arr = [[12, 'AAA'], [12, 'BBB'], [12, 'CCC'],[28, 'DDD'], [18, 'CCC'],[12, 'DDD'],[18, 'CCC'],[28, 'DDD'],[28, 'DDD'],[58, 'BBB'],[68, 'BBB'],[78, 'BBB']];
arr.sort(function(a,b) {
return a[0]-b[0]
});
As previously said, you should use a custom sort function. Here's one that would do exactly what you want.
var arr = [];
arr[0] = [1, 'Peter', 3];
arr[1] = [1, 'Mary', 2];
arr[2] = [0, 'David', 5];
arr[3] = [0, 'John', 4];
arr[4] = [0, 'Billy', 1];
arr.sort(function (a,b) {
if (a[0] < b[0]) return 1;
if (a[0] > b[0]) return -1;
if (a[2] > b[2]) return 1;
if (a[2] < b[2]) return -1;
return 0;
});
array.sort( function (a,b) {
if (a[0] > b[0]) return 1;
if (a[0] < b[0]) return -1;
if (a[2] > b[2]) return 1;
if (a[2] < b[2]) return -1;
return 0;
});