Stack Overflow Asked by Eymerich on December 26, 2020
I have array of objects. I want sort it leave some elements in the same position (with b="NOT")
var a=[{a:1,b:"YES"},{a:2,b:"YES"},{a:5,b:"NOT"},{a:0,b:"NOT"},{a:0,b:"YES"}]
function sortc(x,y){
if (x.b=="NOT" || y.b=="NOT")
return Infinity ;
return (Number(x.a)-Number(y.a))
}
console.log(a.sort(sortc));
the result is :
0: {a: 1, b: "YES"}
1: {a: 2, b: "YES"}
2: {a: 5, b: "NOT"}
3: {a: 0, b: "NOT"}
4: {a: 0, b: "YES"}
The expected result was ( with sort components with b="YES".) :
{ "a": 0, "b": "YES" }
{ "a": 1, "b": "YES" }
{ "a": 5, "b": "NOT" }
{ "a": 0, "b": "NOT" }
{ "a": 2, "b": "YES" }
You cannot only sort some items using the Array#sort()
method - you either sort all or none. You don't define the position of the items, either - you only have to define their relationship to other items and the sorting algorithm will take care of the rest.
What you can do as a workaround is
var a = [
{ a: 1, b: "YES" },
{ a: 2, b: "YES" },
{ a: 5, b: "NOT" },
{ a: 0, b: "NOT" },
{ a: 0, b: "YES" }
]
//get only `b: "YES"` items
const dataToSort = a.filter(item => item.b === "YES");
//sort them
dataToSort.sort((x, y) => x.a - y.a);
//replace only items that need to be sorted
const it = dataToSort.values()
for (let i = 0; i < a.length; i++) {
if (a[i].b === "NOT")
continue;
a[i] = it.next().value;
}
console.log(a);
For the record, the final loop can just be replaced with even shorter with more iterator usage, although it might be slightly more confusing:
const it = dataToSort.values()
for (const [key, item] of a.entries()) { //use the key-value iterator from the array
if (item.b === "NOT")
continue;
[a[key]] = it; //array destructuring internally advances an iterator
}
var a = [
{ a: 1, b: "YES" },
{ a: 2, b: "YES" },
{ a: 5, b: "NOT" },
{ a: 0, b: "NOT" },
{ a: 0, b: "YES" }
]
//get only `b: "YES"` items
const dataToSort = a.filter(item => item.b === "YES");
//sort them
dataToSort.sort((x, y) => x.a - y.a);
//replace only items that need to be sorted
const it = dataToSort.values()
for (const [key, item] of a.entries()) {
if (item.b === "NOT")
continue;
[a[key]] = it;
}
console.log(a);
Finally, this can be made somewhat more convenient with helper generator function and few small utility functions
/* library code */
const transformArg = transform => f => (...args) => f(transform(...args));
function* filter(predicate, it) {
for (const item of it) {
if (predicate(item))
yield item;
}
}
/* /library code */
var a = [
{ a: 1, b: "YES" },
{ a: 2, b: "YES" },
{ a: 5, b: "NOT" },
{ a: 0, b: "NOT" },
{ a: 0, b: "YES" }
]
/* helpers */
//extract the `b` key in this case so we don't need to repeat it.
const getSortableAttribute = transformArg(({b}) => b);
//get the value from key-value pair
const getValue = transformArg(([, value]) => value);
//check if the attribute is "YES"
const isSortable = getSortableAttribute(attr => attr === "YES");
const dataToSort = a.filter(isSortable);
dataToSort.sort((x, y) => x.a - y.a);
const it = dataToSort.values()
//iterate only over sortable key-value pairs by re-using the `isSortable` filter
for (const [key, item] of filter(getValue(isSortable), a.entries())) {
[a[key]] = it;
}
console.log(a);
Correct answer by VLAZ on December 26, 2020
This is an approach by using sort
directly, but shaping the access with a Proxy
for length
and the indices.
const
sortOnly = (array, indices) => new Proxy(array, {
get (target, prop) {
if (isFinite(prop)) return target[indices[prop]];
if (prop === 'length') return indices.length;
return target[prop];
},
set (target, prop, receiver) {
target[indices[prop]] = receiver;
return true;
}
}),
array = [{ a: 1, b: "YES" }, { a: 2, b: "YES" }, { a: 5, b: "NOT" }, { a: 0, b: "NOT" }, { a: 0, b: "YES" }];
sortOnly(array, [...array.keys()].filter(i => array[i].b !== 'NOT'))
.sort((a, b) => a.a - b.a)
console.log(array);
.as-console-wrapper { max-height: 100% !important; top: 0; }
Answered by Nina Scholz on December 26, 2020
Get help from others!
Recent Answers
Recent Questions
© 2024 TransWikia.com. All rights reserved. Sites we Love: PCI Database, UKBizDB, Menu Kuliner, Sharing RPP