Фильтровать массив объектов с помощью вложенных массивов

#javascript

#javascript

Вопрос:

У меня есть следующий массив:

 const arr = [
  {
    id: 1,
    food: ['cola', 'pizza pie'],
    size: [{value: 12}, {value: 14}],
  },
  {
    id: 2,
    food: ['water', 'wine', 'pasta'],
    size: [{value: 15}, {value: 19}],
  },
  {
    id: 3,
    food: ['water', 'wine', 'pasta'],
    size: [{value: 1}, {value: 13}],
  },
];

  

Мне нужно отфильтровать этот массив следующим образом:
Если у меня одинаковые значения ‘food’, элемент массива, который имеет наибольшее значение ‘size-> value’, должен быть оставлен, остальные удалены.

Ожидаемый результат:

 const arr = [
  {
    id: 1,
    food: ['cola', 'pizza pie'],
    size: [{value: 12}, {value: 14}],
  },
  {
    id: 2,
    food: ['water', 'wine', 'pasta'],
    size: [{value: 15}, {value: 19}],
  },
];
  

Каков наилучший способ для этого?

Комментарии:

1. С какими проблемами вы столкнулись?

2. Этот сайт не является сервисом для написания кода, вам нужно сделать попытку. Мы будем рады помочь, если у вас возникнут проблемы с этим, при условии, что вы дадите нам правильное описание проблемы.

3. Какова связь между атрибутами food и size?

4. Конечно, в массиве должно быть три записи size для ['water', 'wine', 'pasta'] ?

5. Вот ваша подсказка: сопоставьте свой массив верхнего уровня с подмассивами, чтобы поместить все «одинаковые» элементы — элементы, которые имеют одинаковые ингредиенты в подмассивах. Затем отсортируйте эти подмассивы и возьмите первое значение из каждого из них.

Ответ №1:

Ваше требование немного расплывчато — особенно когда вы сказали:

Если у меня одинаковые значения ‘food’, элемент массива, который имеет наибольшее значение ‘size-> value’, должен быть оставлен, остальные удалены.

Но вот подход, использующий Array.prototype.reduce (предполагающий, что сравнение проводится между общей суммой значений размера при обнаружении дубликатов). Я прокомментировал код, чтобы дать представление о том, что происходит.

 const arr = [{
    id: 1,
    food: ['cola', 'pizza pie'],
    size: [{
      value: 12
    }, {
      value: 14
    }],
  },
  {
    id: 2,
    food: ['water', 'wine', 'pasta'],
    size: [{
      value: 15
    }, {
      value: 19
    }],
  },
  {
    id: 3,
    food: ['water', 'wine', 'pasta'],
    size: [{
      value: 1
    }, {
      value: 13
    }],
  },
];

function process(arr) {
  return arr.reduce((acc, curr) => {
    const item = acc.filter(x => curr.food.sort().toString() === x.food.sort().toString()) // check if there is another entry with the same `food` value

    if (item.length) {

      // comparision logic goes here
      const previousSizes = item[0].size.reduce((a, b) => a   b.value, 0) // previous item's total size
      const currentSizes = curr.size.reduce((a, b) => a   b.value, 0) // current item's total size
      if (currentSizes > previousSizes) {
        return [...acc.filter(x => x !== item[0]), curr] //remove the previous item and add the new one
      } else return acc // don't change
    } else return [...acc, curr] // curr is a new item.. so just add it
  }, [])
}

console.log(process(arr))  

Ответ №2:

Следующее сортирует входные данные по продуктам питания, чтобы собрать похожие элементы вместе. Затем он просматривает отсортированные входные данные, удаляя элементы по мере нахождения новых максимумов. Он записывает текущий максимум для каждой группы продуктов в хэш-таблице.

Я думаю, что сложность времени n log(n) и сложность пространства n .

Эта реализация предполагает, что наибольшее значение в массиве каждого размера — это то, о чем вы заботитесь.

Псевдокод:

 00. Create hashtable `hash`
01. Sort array `arr` by food
02. For each item `i` in `arr`
03.   Let `key` be a unique key for `i` based on food
04.   Let `largestSize` be the largest number in `i.size`
05.   if `hash` does not contain `key`
06.     Set value of `key` in `hash` to `largestSize`
07.   else 
08.     if `largestSize` is larger than hash.key
09.       replace `m` and delete previous item in `arr` because current item is larger
10.     else 
11.       delete current item in `arr` because it is too small
12.     end if
13.   end if
14. end for
15. return `arr`
  

 function filter(arr) {
    const hash = {}
    arr.sort(({food: a},{food: b})=>String(a).localeCompare(String(b)))
    for (let x = 0; x < arr.length; x  ) {
        const {food, size} = arr[x]
        const [{ value: largestSize }] = size.sort(({value: a},{value: b})=>a - b).slice(-1)
        const key = String(food)

        if (!hash[key])
            hash[key] = largestSize
        else {
            if (largestSize > hash[key]) {
                arr.splice(x - 1, 1)
                hash[key] = largestSize
            } else
                arr.splice(x, 1)
            --x
        }
    }
    return arr
}

const arr = [
  {
    id: 1,
    food: ['cola', 'pizza pie'],
    size: [{value: 12}, {value: 14}],
  },
  {
    id: 2,
    food: ['water', 'wine', 'pasta'],
    size: [{value: 15}, {value: 19}],
  },
  {
    id: 3,
    food: ['water', 'wine', 'pasta'],
    size: [{value: 1}, {value: 13}],
  },
]

console.log(filter(arr))