What is wrong in this sorting array skipping some elements?

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" }

Stack Overflow Asked by Eymerich on December 26, 2020

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

1. Extract all items that should be sorted.
2. Sort them.
3. Go over the original array and only replace anything that should be sorted, leave the rest of the items in their place.

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];
},
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

Related Questions

How to Deserialize a list of objects from json in flutter

8  Asked on January 28, 2021 by gainz

How to add custom functions to run in Selenium ActionChain/ActionBuilder?

0  Asked on January 27, 2021 by m0bbin

How to pass input variable in structure directive?

1  Asked on January 27, 2021 by alice-messis

How to validate yaml file from python script?

1  Asked on January 27, 2021

How to iterate over a list of floats in python

4  Asked on January 27, 2021 by joeyhoward988

Can I run docker system prune -a without downtime

1  Asked on January 27, 2021 by aswin-george

Calculating total Price of groceries with execptions in Python

4  Asked on January 27, 2021 by shemtheultimate

handling multiple useState inside conditional ternary

2  Asked on January 27, 2021 by kachi-cheong

react-native existing app crash on Android 4.1

0  Asked on January 27, 2021 by s-leg3ndz

Trouble Fetching JSON files on server into Javascript Array

3  Asked on January 27, 2021

HTML table widths set proportionally

1  Asked on January 27, 2021 by mayur-arora

Powershell – Is is possible to extract values from several thousand yaml files and export them to a text file

1  Asked on January 27, 2021 by micim987

I want to insert tables with variable lengths into an sqlite database but I am getting an error stating: Incorrect number of bindings supplied

1  Asked on January 27, 2021 by user13888307

Reducing potential excess of garbage when using primitive types with generics?

1  Asked on January 27, 2021 by heaven

Alsa issues on Raspberry pi

1  Asked on January 27, 2021 by suraj-hebbar-shankar

PyTorch – using param.grad affects learning process? [Solved]

1  Asked on January 26, 2021

How to merge dictionaries with the same key and value in Python

1  Asked on January 26, 2021 by arbin-bulaybulay

AJAX switching HTML

1  Asked on January 26, 2021 by mimi

Using request to return a json value

1  Asked on January 26, 2021 by gta-sprx