Javascript sort object string with numbers - javascript

I have the following JSON object in javascript:
var stuff = [{
"id": "20",
"serial": "0/0/19:46,0/0/149:63"
}, {
"id": "8",
"serial": "0/0/151:215,0/0/151:233"
}, {
"id": "54",
"serial": "0/0/151:26,0/0/151:37"
}, {
"id": "22",
"serial": "0/0/155:29,0/0/155:36"
}, {
"id": "4",
"serial": "0/0/151:48,0/0/151:152"
}];
I would like to know how to sort the object by the "serial" field, leaving it like this (taking into account the value of the integers in the serial string):
var stuff = [{
"id": "20",
"serial": "0/0/19:46,0/0/149:63"
}, {
"id": "54",
"serial": "0/0/151:26,0/0/151:37"
}, {
"id": "4",
"serial": "0/0/151:48,0/0/151:152"
}, {
"id": "8",
"serial": "0/0/151:215,0/0/151:233"
}, {
"id": "22",
"serial": "0/0/155:29,0/0/155:36"
}];
Thanks in advance.

This will do it for you:
var normalizer = /[:\/]/g;
function serialCompare(a, b) {
var alist = a.serial.replace(normalizer, ',').split(','),
blist = b.serial.replace(normalizer, ',').split(','),
i = 0, l = alist.length;
while (alist[i] === blist[i] && i < l) {
i += 1;
};
return (parseInt(alist[i], 10) - parseInt(blist[i], 10));
}
sortedstuff = stuff.sort(serialCompare);
// returns array sorted as you asked
See it in a fiddle.
If you are going to be sorting often, or the list is very long, you should consider creating a "normalized" version of the serial value that gets stored in the object. It could be the array as calculated inside the serialCompare function, or it could be the text number parts padded to the same lengths with leading zeroes.

You have an array of objects, which you want to sort by one of their properties. You could very easily do it like this:
stuff.sort(function(a,b) {return a.serial == b.serial ? 0 : a.serial < b.serial ? -1 : 1;});
Alternatively, you could have a more general function:
function sort(input,prop) {
input.sort(function(a,b) {return a[prop] == b[prop] ? 0 : a[prop] < b[prop] ? -1 : 1;});
}
// call with:
sort(stuff,'serial');

Related

Group the data in an array and get the sum from the array of object values

I am new to react and javascript. Here I am trying to use the lodsh function.
I have an array of object which looks like ,
const data = [{
"Id": "1",
"testone": 100,
"test": 40,
"Original": {
"Id": "11"
},
"__Parent__": {
"Id": "20",
"Status": "INP"
}
}, {
"Id": "2",
"testone": 120,
"test": 20,
"Original": {
"Id": "10"
},
"__Parent__": {
"Id": "21",
"Status": "Book"
}
},{
"Id": "3",
"testone": 110,
"test": 140,
"Original": {
"Id": "11"
},
"__Parent__": {
"Id": "20",
"Status": "INP"
}
}, {
"Id": "4",
"testone": 100,
"test": 40,
"Original": {
"Id": "11"
},
"__Parent__": {
"Id": "20",
"Status": "Val"
}
}]
Here, I have one function which has the product Id . which I am passing from another function =>
cont value = (PID, data) => {
}
So, this function ,
I need do sum , where first I need to take all the object which has the same Id as PID. The Id from object is to be Original.ID. If these matches then after that ,I need to check the status of that objects like , is status is either INP or BOOK then for summation need to take the
testone key value or else need to take the `test` key value.
So, In the given example it will be like ,
Id is 11 which is passed to a function and in the given object 3 objects where it matches.
Now,
while returning sum it will be like ,
100 + 100 + 40 which will be 240.
So, How do I do this . thanks .
I think it's best to do it with Array.reduce if you support IE9 and after.
const sum = data.reduce((total, item) => {
if (item.Original.Id !== PID) return total;
const { status, testone, test } = item;
let addition = 0;
if (status === "INP") addition = testone;
else if (status === "BOOK") addition = test;
return total + addition;
}, 0);

Sorting Json data based on a field

I have a Json data that I need to sort before display it. My Json is as below. I need to sort them based on the ColumnLocation.
[{
"Name": "PieChart",
"Id": "1",
"ColumnLocation": "0",
"RowLocation": "0"
}, {
"Name": "Calendar",
"Id": "2",
"ColumnLocation": "1",
"RowLocation": "0"
}, {
"Name": "FavouriteFilter",
"Id": "3",
"ColumnLocation": "2",
"RowLocation": "0"
}, {
"Name": "FilterResults",
"Id": "4",
"ColumnLocation": "0",
"RowLocation": "1"
}, {
"Name": "Watched",
"Id": "5",
"ColumnLocation": "1",
"RowLocation": "1"
}]
i.e the sorted array should have items in following fashion
col : 0, row 0
col : 0, row 1
col : 1, row 0
col : 1, row 1
No need for lodash/underscore. You can use Array.prototype.sort:
Since your values are strings, you must first parse them into numbers and then compare:
let a = [{"Name":"PieChart","Id":"1","ColumnLocation":"0","RowLocation":"0"},{"Name":"Calendar","Id":"2","ColumnLocation":"1","RowLocation":"0"},{"Name":"FavouriteFilter","Id":"3","ColumnLocation":"2","RowLocation":"0"},{"Name":"FilterResults","Id":"4","ColumnLocation":"0","RowLocation":"1"},{"Name":"Watched","Id":"5","ColumnLocation":"1","RowLocation":"1"}]
let sorted = a.sort((a, b) => parseInt(a.ColumnLocation) - parseInt(b.ColumnLocation));
console.log(sorted);
Short and sweet.
let arr = [{"Name":"PieChart","Id":"1","ColumnLocation":"0","RowLocation":"0"},{"Name":"Calendar","Id":"2","ColumnLocation":"1","RowLocation":"0"},{"Name":"FavouriteFilter","Id":"3","ColumnLocation":"2","RowLocation":"0"},{"Name":"FilterResults","Id":"4","ColumnLocation":"0","RowLocation":"1"},{"Name":"Watched","Id":"5","ColumnLocation":"1","RowLocation":"1"}]
arr.sort ( ( a, b ) => { return parseInt ( a.ColumnLocation ) > parseInt ( b.ColumnLocation ) } );
console.log ( arr );
Note that if you don't convert to a number, the sorting can not be what you expect.
Why not use _.sortBy ( http://underscorejs.org/#sortBy ) ?
var mysortedarray = _.sortBy(myarray, 'ColumnLocation');

Angular JS splice items from the Response based on two parameters

This is my JSON response . I am able to splice out elements from controller side using something like this . Now comes a situation where my employees can have same employee id but different Type . So i would like to remove itesm from the response by comparing both Id & type. For example I need to remove the emplooyee with Id ABC and type D only . How can i splice them out how can i proceed
var searchresponse = [{
"items": [{
"employeeId": "ABC",
"type": "D",
"alive": "Yes"
}, {
"employeeId": "ABC",
"type": "P",
"alive": "Yes"
}, {
"employeeId": "NPK",
"type": "D",
"alive": "Yes"
}, {
"employeeId": "PKN",
"type": "A",
"alive": "Yes"
}],
"more": false
}];
var data1 = ["ABC"];
var data2 = ["D"] //- how to splice ABC also comparing the D
var items = searchresponse[0].items;
for (var i = items.length - 1; i >= 0; i--) {
if (data1.indexOf(items[i].employeeId) != -1) {
items.splice(i, 1);
}
}
If i understand u right.. will it be ok to just extend the if clause?
if (data1.indexOf(items[i].employeeId) != -1 && data2.indexOf(items[i].type) != -1)
Using array.prototype.filter method
var filterd =searchresponse[0].items.filter(function (item) {
return item.employeeId == "ABC"&& item.type== "D"
})
You may Also use underscore.js simple javascript library in your case
var filterd=_.where(searchresponse[0].items, {employeeId: "ABC", type: "D"});
will give you
[{
"employeeId": "ABC",
"type": "D",
"alive": "Yes"
}]
Check this working fiddle

Merging two json array object based on union and intersection

I am trying to merge two json array with objects as element. You may refer to this plunkr file for both json. I have succesfully retrieve the expected final outcome array id, but I do not know how to form back the expected json as below. I am using underscore js for this purpose.
Note: If object exist in newJson and not in currentJson, after merge, it will be inactive state by default.
I am not sure whether I am using the correct approach. This is what I have try:
var newJsonID = _.pluck(newJson, 'id');
var currentJsonID = _.pluck(currentJson, 'id');
var union = _.union(newJsonID, currentJsonID);
var intersection = _.intersection(currentJsonID, newJsonID);
var final = _.difference(union, _.difference( currentJsonID, intersection);
Expected Final Outcome:
[
{
"id": "12",
"property1Name": "1"
"status": "inactive"
},
{
"id": "11",
"property1Name": "1"
"status": "inactive"
},
{
"id": "10",
"property1Name": "1"
"status": "inactive"
},
{
"id": "9",
"property1Name": "1"
"status": "active"
}
]
A solution in plain Javascript with two loops and a hash table for lookup.
function update(newArray, currentArray) {
var hash = Object.create(null);
currentArray.forEach(function (a) {
hash[a.id] = a.status;
});
newArray.forEach(function (a) {
a.status = hash[a.id] || 'inactive';
});
}
var newJson = [{ "id": "12", "property1Name": "1" }, { "id": "11", "property1Name": "1" }, { "id": "10", "property1Name": "1" }, { "id": "9", "property1Name": "1" }],
currentJson = [{ "id": "10", "property1Name": "1", "status": "inactive" }, { "id": "9", "property1Name": "1", "status": "active" }, { "id": "8", "property1Name": "1", "status": "active" }, { "id": "7", "property1Name": "1", "status": "inactive" }];
update(newJson, currentJson);
document.write('<pre>' + JSON.stringify(newJson, 0, 4) + '</pre>');

JavaScript multi-level sorting with multi dimension array

I have a JSON object like below:
[
{
"name": "Robert",
"age":32,
"country": "UK"
},
{
"name": "Prasad",
"age":28,
"country": "India"
},
{
"name": "Benny",
"age":45,
"country": "USA"
},
{
"name": "Robin",
"age":34,
"country": "UK"
},
{
"name": "Bob",
"age":20,
"country": "India"
}
]
I have applied the array sorting for "name" column alone. I want to apply sort for “name” column first and then “age”.
This is how i sort the array by name:
var sort_by = function(field, reverse, primer){
var key = primer ?
function(x) {return primer(x[field])} :
function(x) {return x[field]};
reverse = [-1, 1][+!!reverse];
return function (a, b) {
return a = key(a), b = key(b), reverse * ((a > b) - (b > a));
}
}
Call the sort function:
arrayToSort.sort(
sort_by( “name”, true, function(a){
return a.toUpperCase();
}) );
How can I get the array sorted like below?
[{
"name": "Bob",
"age":20,
"country": "India"
},
{
"name": "Benny",
"age":45,
"country": "USA"
},
{
"name": "Prasad",
"age":28,
"country": "India"
},
{
"name": "Robert",
"age":32,
"country": "UK"
},
{
"name": "Robin",
"age":34,
"country": "UK"
}]
I think what you are looking for is a way to "chain" sort_by(..) calls so as to be able to operate on more than one field.
Below is a slightly modified version of your code. Its pretty much self-explanatory.
arrayToSort = [ ...];
var sort_by = function(field, reverse, primer){
var key = primer ?
function(x) {return primer(x[field]); }:
function(x) {return x[field] };
reverse = [-1, 1][+!!reverse];
return function (a, b) {
a = key(a);
b = key(b);
return a==b ? 0 : reverse * ((a > b) - (b > a));
//^ Return a zero if the two fields are equal!
}
}
var chainSortBy = function(sortByArr) {
return function(a, b) {
for (var i=0; i<sortByArr.length; i++) {
var res = sortByArr[i](a,b);
if (res != 0)
return res; //If the individual sort_by returns a non-zero,
//we found inequality, return the value from the comparator.
}
return 0;
}
}
arrayToSort.sort(
chainSortBy([
sort_by( "name", true, function(a){
return a.toUpperCase();
}),
sort_by("age", true, null)
])
);
console.log(arrayToSort); //Check browser console.
For output: check the JSFiddle
The solution is back to native, just :
function orderByProp(arr,prop){
var order = [], ordered=[];
//create temp ID and Save the real index
for(i=0; i < arr.length;++i){ order.push(arr[i][prop]+"-:-"+i);}
ordered.sort();
for(i=0; i < arr.length;++i){
var val = order.split("-:-");
ordered.push(arr[val[1]]); Get the real array by saved index
}
return ordered;
}
// Apply
var arr = [{
"name": "Bob",
"age":20,
"country": "India"
},
{
"name": "Benny",
"age":45,
"country": "USA"
},
{
"name": "Prasad",
"age":28,
"country": "India"
},
{
"name": "Robert",
"age":32,
"country": "UK"
},
{
"name": "Robin",
"age":34,
"country": "UK"
}];
var sort = orderByProp(arr,"name");
i'm not tested this. but hope it could solve your problems
This is relatively trivial with the Array.sort method by using the || operator, where it will use the second value if the first comparison returns 0, meaning the value was the same:
const data = [
{
"name": "Robert",
"age": 32,
},
{
"name": "David",
"age": 24,
},
{
"name": "Robert",
"age": 28,
},
];
const sortedData = data.sort((a, b) => a.name.localeCompare(b.name) || a.age - b.age);
console.log(sortedData);
Credit for this goes to #NinaScholz for her answer here.

Categories