3

I have multiple numeric arrays where elements with a value of -1 are located in certain positions. Arrays must be sorted in ascending order without changing the positions of elements with a value of -1. I can't create a right comparison function in sort(function (a,b){}). Тhe results of sorting the following arrays should look like this:

[-1,150,190,170,-1,-1,160,180] result [-1,150,160,170,-1,-1,180,190].
[-1,2,-1,8,-1,4]) result [-1,2,-1,4,-1,8].
[-1,-1,-1,-1,-1]) result [-1,-1,-1,-1,-1].
[4,2,9,11,2,16]) result [2,2,4,9,11,16].

This code

return x.sort(function (a,b) {
    if (a==-1) return 0;
    // if (b==-1) return 0;
    if (a < b) return -1;
    if (a > b) return 1;
    return 0;
});

doesn't work correctly in first example, result look like this [-1,150,160,170,190,-1,-1,180]. And doesn't work at all on second example.

3
  • I can't create a right comparison function what have you tried? Can you include the code you've tried so far? Commented Jan 4, 2021 at 11:25
  • 2
    I don't think you can do that since that would mean the same -1 value has different positions relative to other elements. A possible solution would be to get the indexes of all -1 elements, remove them from the array, sort the array, and reinsert the values. Commented Jan 4, 2021 at 11:26
  • 2
    "I can't create a right comparison function" - you've done well to recognise that :-) It is impossible to create a comparison function for that, since you are not trying to sort the elements by a position-independent order Commented Jan 4, 2021 at 11:36

3 Answers 3

3

You can do the following,

function sortArr(arr) {
  const sortedArr = arr.filter(item => item !== -1).sort((a,b) => a-b);
  let cnt = 0;
  return arr.map(item => {
    if (item === -1) return -1;
    else return sortedArr[cnt++];
  });
}
console.log(sortArr([-1,150,190,170,-1,-1,160,180]));
console.log(sortArr([-1,2,-1,8,-1,4]));
console.log(sortArr([-1,-1,-1,-1,-1]));
console.log(sortArr([4,2,9,11,2,16]));

Sign up to request clarification or add additional context in comments.

Comments

1

This is an approach by using sort directly, but shaping the access with a Proxy for length and the indices.

const
    sort = (array, sortFn, filterFn = _ => true) => {
        const indices = [...array.keys()].filter(i => filterFn(array[i]));
        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;
            }
        })
        .sort(sortFn);

        return array;
    };    
    
console.log(...sort(
    [-1, 150, 190, 170, -1, -1, 160, 180],
    (a, b) => a - b,
    v => v !== -1
));

1 Comment

А masterpiece approach for all possible occasions. Excellent
1

What I would do is filter out the negative numbers into another array sort, and then pop back into the original..

eg.

function sorter(arr) {
  const nums = arr.filter(
    b => b >= 0).sort((a,b) => b - a);
  for (let l = 0; l < arr.length; l += 1) { 
    if (arr[l] >= 0) arr[l] = nums.pop();
  }
  return arr;
}

console.log(sorter(
  [-1,150,190,170,-1,-1,160,180]).
  join(','));
console.log(sorter(
  [-1,2,-1,8,-1,4]).
  join(','));
console.log(sorter(
  [-1,-1,-1,-1,-1]).
  join(',')
  );
console.log(sorter(
  [4,2,9,11,2,16]).
  join(',')
  );

2 Comments

Your code doesn't work at all. Look on results after code snippet run [-1,150,190,170,-1,-1,160,180] [-1,2,-1,8,-1,4] [-1,-1,-1,-1,-1] [4,2,9,11,2,16]
@Artur Well spotted, teach me not to check my results thoroughly.. :), updated!!.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.