0

I have two arrays like below:

const arr = [ 4, 5 ]
const arr2 = [
{
    "id": 1
    "type":[4]
},{
    "id": 2
    "type":[4,1]
},{
    "id": 3
    "type":[4,8,3]
},{
    "id": 4
    "type":[4,5]
}
]

how to sort arr2 in this way, that:

  1. such that if the type of arr2 contains all elements in arr then those objects are at the very top of the list,

  2. when it has at least one element with arr2 then should be in the next position,

  3. and the last ones should be objects that only have one (the only one in type) listed in arr,

so, the result should be:

const arr2 = [
{
    "id": 4
    "type":[4,5]
},{
    "id": 2
    "type":[4,1]
},{
    "id": 3
    "type":[4,8,3]
},{
    "id": 1
    "type":[4]
}
]

I try to do this with js` function like below:

arr2.sort(e => e.type.includes(arr))

but it not working correctly, can omeone tell me how to sort arr2 in the provided ways? thanks for any help!

1
  • 1
    FYI, the sort function in Javascript, when called with a callback, expects a callback that takes two parameters and returns either -1, 0, or 1. It should return -1 if the first parameter should come before the second, 0 if the two parameters are equal, and 1 if the the first parameter should come after the second. This isn't a complete answer, but it is part of why your attempted solution does not work. developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/… Commented May 13, 2021 at 8:12

3 Answers 3

3

You could count the occurences and sort descending.

const
    getCount = array => types.reduce((s, t) => s + array.includes(t), 0),
    types = [4, 5],
    data = [{ id: 6, type: [] }, { id: 1,  type: [4] }, { id: 2,  type: [4, 1] }, { id: 3,  type: [4, 8, 3] }, { id: 4, type: [4, 5] }, { id: 5, type: [1, 2, 3] }];
  
data.sort(({ type: a}, { type: b }) => {
    const
        countA = getCount(a),
        countB = getCount(b);

    return countB - countA
        || (countA === 1 && a.length === 1) - (countB === 1 && b.length === 1);
});

console.log(data);
.as-console-wrapper { max-height: 100% !important; top: 0; }

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

1 Comment

Thanks, but object with id: 1 must be last one
2

You can do this elegantly by adding a weight function, so that more important elements get less "weight" and literally rise toward the beginning:

const KEYS = [4, 5]

const arr2 = [
    {"id": 1,"type": [4]}, 
    {"id": 2,"type": [4, 1]}, 
    {"id": 3,"type": [4, 8, 3]}, 
    {"id": 4,"type": [4, 5]}
]

function weight(a) {
    let common = a.reduce((cnt, x) => cnt + KEYS.includes(x), 0)

    if (common === KEYS.length)
        return 0

    if (common > 0 && a.length > 1)
        return 1000 + a.length

    if (common > 0)
        return 10_000

    return Infinity
}

arr2.sort(({type: x}, {type: y}) => weight(x) - weight(y))

console.log(arr2)

Comments

1

const arr = [4, 5];
const arr2 = [
  {
    id: 1,
    type: [4],
  },
  {
    id: 2,
    type: [4, 1],
  },
  {
    id: 3,
    type: [4, 8, 3],
  },
  {
    id: 4,
    type: [4, 5],
  },
];

console.log(
  arr2
    .sort((e) => -e.type.length)
    .sort((e) =>
      arr.every((aType) => e.type.includes(aType))
        ? -1
        : e.type.includes(arr)
        ? 0
        : 1,
    ),
);

First we sort the array by the length to satisfy condition (3), to have object with one element type at the end.

This pre-sorted array still needs to be sorted according to (1) and (2).

To test for (1) we look at return value of every, if it's true we return -1 to have it at the end of the resulting array. If it's not true, we need to test for (2).

The remaining test for (2) is simply done by another call to includes, if element is found we return 0, means it remains at the position of the pre-sorted array. If it's not found we sort it in at the end of the array by returning 1.

1 Comment

Thanks, can you paste your code as snippets?

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.