Related
var data = {
"input": [{
"countA": 1,
"countB": 10
},
{
"countA": 15,
"countB": 13
},
{
"countA": 26,
"countB": 24
},
{
"countA": 6,
"countB": 25
},
{
"countA": 15,
"countB": 20
}
]
};
var sorted = data.input.sort(function(a, b) {
return a['countB'] < b['countB'] ? 1 : -1;
});
console.log(sorted);
The outcome after the first sorting should be after another sorting:
[
{
"countA": 6,
"countB": 25
},
{
"countA": 15,
"countB": 20
},
{
"countA": 1,
"countB": 10
}
{
"countA": 26,
"countB": 24
},
{
"countA": 15,
"countB": 13
}
]
So, it should be the highest of "countB" and then descending as long as "countB" is higher than "countA". So far I tried multiple ways, but there's no outcome so far.
Thanks for any help!
You could sort by the result of the comparison of countB > countA and then by the value of countB.
const
data = [{ countA: 1, countB: 10 }, { countA: 15, countB: 13 }, { countA: 26, countB: 24 }, { countA: 6, countB: 25 }, { countA: 15, countB: 20 }];
data.sort((a, b) =>
(b.countB > b.countA) - (a.countB > a.countA) ||
b.countB - a.countB
);
console.log(data);
.as-console-wrapper { max-height: 100% !important; top: 0; }
You can first extract the values of the array when "countb" >= "countA", sort that array then add the remaining values at the end (note that for order is kept for when "countb" < "countA") :
var data = {
"input": [{
"countA": 1,
"countB": 10
},
{
"countA": 15,
"countB": 13
},
{
"countA": 26,
"countB": 24
},
{
"countA": 6,
"countB": 25
},
{
"countA": 15,
"countB": 20
}
]
};
const ElementsToSort = data.input.filter(elem => elem.countA <= elem.countB);
const RemainingElements = data.input.filter(elem => ElementsToSort.indexOf(elem) < 0);
// sort as you did
const PartiallySorted = ElementsToSort.sort(function(a, b) {
return a['countB'] < b['countB']
? 1
: a['countB'] > b['countB']
? -1
: 0;
});
//add the remaining values
const sorted = PartiallySorted.concat(RemainingElements);
console.log(sorted);
I have this array of objects
const data = [
{ id: 0, ALT_VALUE: 11, DLT_VALUE: 76 },
{ id: 1, ALT_VALUE: 80, DLT_VALUE: 48 },
{ id: 2, ALT_VALUE: 90, DLT_VALUE: 100 },
{ id: 3, ALT_VALUE: 12, DLT_VALUE: 70 },
{ id: 4, ALT_VALUE: 90, DLT_VALUE: 100 },
{ id: 5, ALT_VALUE: 13, DLT_VALUE: 49 },
{ id: 6, ALT_VALUE: 76, DLT_VALUE: 70 },
{ id: 7, ALT_VALUE: 9, DLT_VALUE: 15 },
];
and I would like to filter it dynamically based on this array of objects
const filters = [
{ parameter: "ALT_VALUE", min: 8, max: 100 },
{ parameter: "DLT_VALUE", min: 30, max: 50 },
];
based on the filters, the final result supposed to be
[
{ id: 5, ALT_VALUE: 13, DLT_VALUE: 49 },
{ id: 1, ALT_VALUE: 80, DLT_VALUE: 48 },
]
I tried with this
const result = data.filter((el) => {
return filters.filter((f) => {
if (el[f.parameter] > f.min && el[f.parameter] < f.max) {
return el;
}
});
});
But I get all of the data
[
{ id: 0, ALT_VALUE: 11, DLT_VALUE: 76 },
{ id: 1, ALT_VALUE: 80, DLT_VALUE: 48 },
{ id: 2, ALT_VALUE: 90, DLT_VALUE: 100 },
{ id: 3, ALT_VALUE: 12, DLT_VALUE: 70 },
{ id: 4, ALT_VALUE: 90, DLT_VALUE: 100 },
{ id: 5, ALT_VALUE: 13, DLT_VALUE: 49 },
{ id: 6, ALT_VALUE: 76, DLT_VALUE: 70 },
{ id: 7, ALT_VALUE: 9, DLT_VALUE: 15 }
]
In your function, filters.filter() returns an Array, which JavaScript sees as a truthy value. This means that every item in data passes your filter (each iteration yields an array, empty or not, which is interpreted as true), and everything is included.
By having your filter return a Boolean value instead, you can avoid JavaScript coercing an Array to a Boolean value:
const result = data.filter((el) => {
// every will only return true if all filters match,
// else it will return false
return filters.every((f) => {
if (el[f.parameter] > f.min && el[f.parameter] < f.max) {
return el;
}
});
});
Since you want all the filters to be respected you need to use every instead of filter.
If you use filter if any of filter rule is match it will result in adding that to final output.
const data = [
{ id: 0, ALT_VALUE: 11, DLT_VALUE: 76 },
{ id: 1, ALT_VALUE: 80, DLT_VALUE: 48 },
{ id: 2, ALT_VALUE: 90, DLT_VALUE: 100 },
{ id: 3, ALT_VALUE: 12, DLT_VALUE: 70 },
{ id: 4, ALT_VALUE: 90, DLT_VALUE: 100 },
{ id: 5, ALT_VALUE: 13, DLT_VALUE: 49 },
{ id: 6, ALT_VALUE: 76, DLT_VALUE: 70 },
{ id: 7, ALT_VALUE: 9, DLT_VALUE: 15 },
];
const filters = [
{ parameter: "ALT_VALUE", min: 8, max: 100 },
{ parameter: "DLT_VALUE", min: 30, max: 50 },
];
const result = data.filter((el) => {
return filters.every((f) => {
if (el[f.parameter] > f.min && el[f.parameter] < f.max) {
return el;
}
});
})
console.log(result)
Please use every instead of second filter
Array.prototype.every will return true if every element in the array matches your condition in the callback
const data = [
{ id: 0, ALT_VALUE: 11, DLT_VALUE: 76 },
{ id: 1, ALT_VALUE: 80, DLT_VALUE: 48 },
{ id: 2, ALT_VALUE: 90, DLT_VALUE: 100 },
{ id: 3, ALT_VALUE: 12, DLT_VALUE: 70 },
{ id: 4, ALT_VALUE: 90, DLT_VALUE: 100 },
{ id: 5, ALT_VALUE: 13, DLT_VALUE: 49 },
{ id: 6, ALT_VALUE: 76, DLT_VALUE: 70 },
{ id: 7, ALT_VALUE: 9, DLT_VALUE: 15 },
];
const filters = [
{ parameter: "ALT_VALUE", min: 8, max: 100 },
{ parameter: "DLT_VALUE", min: 30, max: 50 },
];
const result = data.filter((el) => {
return filters.every((f) => {
if (el[f.parameter] > f.min && el[f.parameter] < f.max) {
return el;
}
});
});
console.log(result)
While researching on the mechanism for sorting arrays in JavaScript by multiple properties/fields/attributes, I've come across this article. For my personal project I have utilized the solution offered by #chriskelly.
function comparator(attrs) {
return function (v1, v2) {
return attrs
.map(function (fld) {
var ad = 1;
if (fld[0] === '-') {
ad = -1;
fld = fld.substring(1);
}
if (v1[fld] > v2[fld]) return ad;
if (v1[fld] < v2[fld]) return -(ad);
return 0;
})
.reduce(function nonZero (v3, v4) {
return v3 ? v3 : v4;
}, 0);
};
}
My input array is the following:
[{"name":"Pass9884881","fld1d":10,"fld2d":25,"fld4d":383,"fld3d":626490,"fld5a":0,"date":"09/27/2021","time":"18:23:31"},
{"name":"Driver1","fld1d":"10","fld2d":25,"fld4d":356,"fld3d":559650,"fld5a":0,"date":"10/18/2021","time":"14:48:17"},
{"name":"Driver321","fld1d":10,"fld2d":22,"fld4d":346,"fld3d":554400,"fld5a":1,"date":"08/08/2021","time":"22:35:03"},
{"name":"Driverxyz","fld1d":9,"fld2d":25,"fld4d":350,"fld3d":497190,"fld5a":0,"date":"07/26/2021","time":"14:23:33"},
{"name":"Pass1974761","fld1d":"9","fld2d":25,"fld4d":316,"fld3d":477290,"fld5a":0,"date":"10/11/2021","time":"19:20:33"},
{"name":"Pass7374147","fld1d":"9","fld2d":23,"fld4d":279,"fld3d":376750,"fld5a":0,"date":"10/10/2021","time":"20:13:15"},
{"name":"Driver0","fld1d":8,"fld2d":25,"fld4d":286,"fld3d":435940,"fld5a":0,"date":"07/26/2021","time":"12:31:42"},
{"name":"Pass1536735","fld1d":"8","fld2d":25,"fld4d":236,"fld3d":329880,"fld5a":0,"date":"10/09/2021","time":"17:19:14"},
{"name":"#xxxxyyyy","fld1d":"10","fld2d":25,"fld4d":329,"fld3d":500440,"fld5a":0,"date":"11/04/2021","time":"00:04:17"},
{"name":"Pass7668209","fld1d":"8","fld2d":24,"fld4d":203,"fld3d":267150,"fld5a":0,"date":"10/09/2021","time":"00:22:18"}]
It meant to be sorted by fld1d (desc), fld2d (desc), fld3d (desc), fld4d (desc), fld5a (asc), date (asc) and time (asc). When the object with "name":"#xxxxyyyy" is placed the last or next to the last in the input data (gets read in from an external file in the code), the resulting sorted array appears incorrect:
Incorrectly sorted array
However, if I move that object in the input file to the 8th position (out of 10) or above, the resulting sorted array is correct:
Correctly sorted array
I ought to admit, I am not a professional developer - just an interested party who somewhat learnt to follow examples, and I'm having hard time explaining the discrepancy in the results.
Suggestions would be greatly appreciated.
You could take a simplified approach and chain all sorting crieria by taking the delta or use a string comparison.
const
getISO = (date, time) => `${date.slice(3, 5)}-${date.slice(0, 2)}-${date.slice(6, 10)}T${time}`;
data = [{ name: "Pass9884881", fld1d: 10, fld2d: 25, fld4d: 383, fld3d: 626490, fld5a: 0, date: "09/27/2021", time: "18:23:31" }, { name: "Driver1", fld1d: "10", fld2d: 25, fld4d: 356, fld3d: 559650, fld5a: 0, date: "10/18/2021", time: "14:48:17" }, { name: "Driver321", fld1d: 10, fld2d: 22, fld4d: 346, fld3d: 554400, fld5a: 1, date: "08/08/2021", time: "22:35:03" }, { name: "Driverxyz", fld1d: 9, fld2d: 25, fld4d: 350, fld3d: 497190, fld5a: 0, date: "07/26/2021", time: "14:23:33" }, { name: "Pass1974761", fld1d: "9", fld2d: 25, fld4d: 316, fld3d: 477290, fld5a: 0, date: "10/11/2021", time: "19:20:33" }, { name: "Pass7374147", fld1d: "9", fld2d: 23, fld4d: 279, fld3d: 376750, fld5a: 0, date: "10/10/2021", time: "20:13:15" }, { name: "Driver0", fld1d: 8, fld2d: 25, fld4d: 286, fld3d: 435940, fld5a: 0, date: "07/26/2021", time: "12:31:42" }, { name: "Pass1536735", fld1d: "8", fld2d: 25, fld4d: 236, fld3d: 329880, fld5a: 0, date: "10/09/2021", time: "17:19:14" }, { name: "#xxxxyyyy", fld1d: "10", fld2d: 25, fld4d: 329, fld3d: 500440, fld5a: 0, date: "11/04/2021", time: "00:04:17" }, { name: "Pass7668209", fld1d: "8", fld2d: 24, fld4d: 203, fld3d: 267150, fld5a: 0, date: "10/09/2021", time: "00:22:18" }],
data.sort((a, b) =>
b.fld1d - a.fld1d ||
b.fld2d - a.fld2d ||
b.fld3d - a.fld3d ||
b.fld4d - a.fld4d ||
a.fld5a - b.fld5a ||
getISO(a.date, a.time).localeCompare(getISO(b.date, b.time))
);
console.log(data);
.as-console-wrapper { max-height: 100% !important; top: 0; }
I've been trying to merge data and get this result:
data = [{serviceID: 22, quantite: 120, typeConviveId: 6},
{serviceID: 23, quantite: 240, typeConviveId: 6},
{serviceID: 24, quantite: 100, typeConviveId: 7},
{serviceID: 25, quantite: 150, typeConviveId: 7}]
what needed at end :
result: [ { "22": "120", "23": "240", "typeConviveId": "6"},
{ "24": "100", "25": "150", "typeConviveId": "7" } ]
You can use a combination of Array.prototype.map, Array.prototype.filter and Array.prototype.reduce, along with a list of unique typeConviveId deduped using a Set with [...new Set(data.map(x=>x.typeConviveId))]:
const data = [{serviceID: 22, quantite: 120, typeConviveId: 6}, {serviceID: 23, quantite: 240, typeConviveId: 6}, {serviceID: 24, quantite: 100, typeConviveId: 7}, {serviceID: 25, quantite: 150, typeConviveId: 7}];
const result = [...new Set(data.map(x => x.typeConviveId))].map(
id => data
.filter(x => x.typeConviveId === id)
.reduce((acc, val) => {
return { ...acc,
[val.serviceID]: '' + val.quantite
}
}, {
typeConviveId: '' + id
})
);
console.log(result);
You can use array reduce & in the callback function use findIndex to get the object which has same typeConviveId. findIndex will return the index of the object which has same findIndex from the accumulator array which is represented by acc. In fiindIndex is -1 then create a new object with required keys and push it in the accumulator array. If there already exist an array with same typeConviveId then just update the object with new key
let data = [{
serviceID: 22,
quantite: 120,
typeConviveId: 6
},
{
serviceID: 23,
quantite: 240,
typeConviveId: 6
},
{
serviceID: 24,
quantite: 100,
typeConviveId: 7
},
{
serviceID: 25,
quantite: 150,
typeConviveId: 7
},
{
serviceID: 25,
quantite: 250,
typeConviveId: 7
}
]
let newData = data.reduce(function(acc, curr) {
let findIndex = acc.findIndex(function(item) {
return item.typeConviveId === curr.typeConviveId;
})
if (findIndex === -1) {
acc.push({
typeConviveId: curr.typeConviveId,
[curr.serviceID]: curr.quantite
})
} else {
acc[findIndex][curr.serviceID] = curr.quantite
}
return acc;
}, []);
console.log(newData)
The expected result have a problem. If there is a duplicate key for example suppose if the key like 22 i s repeated , then it will have the last value.
{
serviceID: 25,
quantite: 150,
typeConviveId: 7
},
{
serviceID: 25,
quantite: 250,
typeConviveId: 7
}
In this case serviceID in both object is 25, So its value will be 250. It will not have two keys with separate value
I have below object, which can have many careerLevels (I have shown 2 for now):
var input =
{
"careerLevel": "Associate",
"careerLevels": [
{
"201609": 21,
"201610": 22,
"201611": 23,
"careerID": "10000120"
},
{
"201609": 31,
"201610": 32,
"201611": 33,
"careerID": "10000130"
}]
};
I want to check careerID attribute and i need to extract that element which has highest careerID value.
So in this case the output will look like :
var output= {"201609": 31,
"201610": 32,
"201611": 33}
What i have tried is as below :
var res = Math.max.apply(Math, oldArr.careerLevels.map(function (o) { return o.careerID; })) // This gives me the highest careerID value
var highestOrderArr = oldArr.careerLevels.filter(element => {
// i think here i need to make a check for the comparison
});
We can use reduce, to get the highest careerID and output that object.
var input ={
"careerLevel": "Associate",
"careerLevels": [
{
"201609": 21,
"201610": 22,
"201611": 23,
"careerID": "10000120"
},
{
"201609": 31,
"201610": 32,
"201611": 33,
"careerID": "10000130"
}]
};
const out = input.careerLevels.reduce((prev, current) => {
return (prev.careerID > current.careerID) ? prev : current
}, false)
console.log(out);
An alternative is sorting and getting the last object.
var input = { "careerLevel": "Associate", "careerLevels": [{ "201609": 21, "201610": 22, "201611": 23, "careerID": "10000120" }, { "201609": 31, "201610": 32, "201611": 33, "careerID": "10000130" } ]},
highest = input.careerLevels.sort((a, b) => a.careerID - b.careerID).pop();
console.log(highest);
.as-console-wrapper { max-height: 100% !important; top: 0; }
Using the function reduce
var input = { "careerLevel": "Associate", "careerLevels": [{ "201609": 21, "201610": 22, "201611": 23, "careerID": "10000120" }, { "201609": 31, "201610": 32, "201611": 33, "careerID": "10000130" } ]},
highest = input.careerLevels.reduce((a, c) => c.careerID > a.careerID ? c : a, {careerID: Number.MIN_SAFE_INTEGER});
console.log(highest);
.as-console-wrapper { max-height: 100% !important; top: 0; }