Как удалить элементы из массива с помощью объекта фильтра

Я хотел бы отфильтровать массив с учетом объекта фильтра

function remove (array, filter) {
  // magic
}

filter — объект переменного размера с любым количеством ключей/значений

Он должен действовать следующим образом

const products = [
  { size: 'S', color: 'blue' },
  { size: 'L', color: 'red' },
  { size: 'S', color: 'red' },
  { size: 'L', color: 'green' },
]

// With a filter of keys/value it filters for the existing key/values
const filteredProducts1 = remove(products, { size: 'S', color: 'red' })

console.info(filteredProducts1)
/*
[
  { size: 'S', color: 'blue' },
  { size: 'L', color: 'red' },
  { size: 'L', color: 'green' },
]
*/

// With less key/value than the object array, it filters for the existing key/value
const filteredProducts2 = remove(products, { size: 'S' })

console.info(filteredProducts2)
/*
[
  { size: 'L', color: 'red' },
  { size: 'L', color: 'green' },
]
*/

// With more keys/values than the object array it discard the non-existing key/value
const filteredProducts1 = remove(products, { size: 'S', color: 'red', type: 'dress' })

console.info(filteredProducts1)
/*
[
  { size: 'S', color: 'blue' },
  { size: 'L', color: 'red' },
  { size: 'L', color: 'green' },
]
*/

Моя проблема заключается в создании динамического условия из объекта фильтра

я пытаюсь преобразовать

{ key1: value1, key2: value2, ... , keyN: valueN }

в

condition 1 && condition2 && ... & conditionN

подсказка: массив.каждый

cmgchess 05.04.2023 05:52

мой плохой какой-то лучше подходит в этом случае, так как вы отфильтровываете неудовлетворительные

cmgchess 05.04.2023 05:58

Кстати, как вы получаете M в результатах, когда его нет на входе

cmgchess 05.04.2023 06:19

Это опечатка. Я исправил исходный пост

eakl 06.04.2023 07:18

хорошо, я думаю, что многие уже поняли это

cmgchess 06.04.2023 08:45
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Улучшение производительности загрузки с помощью Google Tag Manager и атрибута Defer
Улучшение производительности загрузки с помощью Google Tag Manager и атрибута Defer
В настоящее время производительность загрузки веб-сайта имеет решающее значение не только для удобства пользователей, но и для ранжирования в...
Безумие обратных вызовов в javascript [JS]
Безумие обратных вызовов в javascript [JS]
Здравствуйте! Юный падаван 🚀. Присоединяйся ко мне, чтобы разобраться в одной из самых запутанных концепций, когда вы начинаете изучать мир...
Система управления парковками с использованием HTML, CSS и JavaScript
Система управления парковками с использованием HTML, CSS и JavaScript
Веб-сайт по управлению парковками был создан с использованием HTML, CSS и JavaScript. Это простой сайт, ничего вычурного. Основная цель -...
JavaScript Вопросы с множественным выбором и ответы
JavaScript Вопросы с множественным выбором и ответы
Если вы ищете платформу, которая предоставляет вам бесплатный тест JavaScript MCQ (Multiple Choice Questions With Answers) для оценки ваших знаний,...
0
5
150
4
Перейти к ответу Данный вопрос помечен как решенный

Ответы 4

Вы можете определить, присутствует ли какая-либо пара ключ-значение в фильтре в каждом объекте в массиве:

function remove(array, filter) {
  return array.filter((obj) => {
    for (const [key, value] of Object.entries(filter)) {
      if (obj[key] === value) return false;
    }
    return true;
  });
}

const products = [
  { size: "M", color: "blue" },
  { size: "S", color: "blue" },
  { size: "L", color: "red" },
  { size: "S", color: "red" },
  { size: "L", color: "green" },
];

console.info(remove(products, { size: "S", color: "red" }));
// [ { size: "M", color: "blue" }, { size: "L", color: "green" } ]

console.info(remove(products, { size: "S" }));
// [ { size: "M", color: "blue" }, { size: "L", color: "red" }, { size: "L", color: "green" } ]

console.info(remove(products, { size: "S", color: "red", type: "dress" }));
// [ { size: "M", color: "blue" }, { size: "L", color: "green" } ]
remove(products, { size: "S", color: "red" }) следует удалить size = S AND color = blue. Ваша функция удаляет любое условие, которое выполняется. не когда все условия соблюдены/
eakl 08.04.2023 09:30
Ответ принят как подходящий

вы можете использовать some, чтобы вернуть true, если хотя бы одно из условий существует и не равно фильтру.
вы даже можете использовать x[k] вместо x.hasOwnProperty(k), если гарантировано, что будут ключи, указывающие на значения с ложными значениями (undefined,null,0..,'').
Также MDN рекомендует Object.hasOwn вместо Object.hasOwnProperty, если ваша среда (браузер/узел) поддерживает это.

function remove (array, filter) {
  return array.filter((x) => Object.entries(filter).some(([k,v]) => x.hasOwnProperty(k) && x[k] !== v))
}

const products = [
  { size: 'S', color: 'blue' },
  { size: 'L', color: 'red' },
  { size: 'S', color: 'red' },
  { size: 'L', color: 'green' },
]

console.info(remove(products, { size: 'S', color: 'red' }))
console.info(remove(products, { size: 'S' }))
console.info(remove(products, { size: 'S', color: 'red', type: 'dress' }))
.as-console-wrapper { max-height: 100% !important; top: 0; }

редактировать решить проблему

remove(products, { type: 'dress' }) удаляет все, что не должно

теперь я отфильтровываю поля из записей фильтра, которые существуют в объекте, чтобы проверить и вернуть весь массив, если записи фильтра пусты

function remove (array, filter) {
  return array.filter((x,i) => {
    const entries =  Object.entries(filter).filter(([k,_]) => x.hasOwnProperty(k))
    if (entries.length === 0) return array
    return entries.some(([k,v]) => x[k] !== v)
  })
}

const products = [
  { size: 'S', color: 'blue' },
  { size: 'L', color: 'red' },
  { size: 'S', color: 'red' },
  { size: 'L', color: 'green' },
]

console.info(remove(products, { size: 'S', color: 'red' }))
console.info(remove(products, { size: 'S' }))
console.info(remove(products, { size: 'S', color: 'red', type: 'dress' }))
console.info(remove(products, { type: 'dress' }))
console.info(remove(products, {}))
.as-console-wrapper { max-height: 100% !important; top: 0; }
remove(products, { type: 'dress' }) удаляет все, что не должно
eakl 08.04.2023 09:21

@eakl можешь проверить еще раз. я не уверен, пропустил ли я какие-либо другие крайние случаи

cmgchess 08.04.2023 10:15

Кажется, это работает нормально. даже если значение равно null или undefined

eakl 08.04.2023 11:26

@eakl, надеюсь, теперь у тебя есть идея, что изменить, когда что-то не работает.

cmgchess 08.04.2023 11:29

Как насчет этого, фильтры переменных будут возвращать массив логических значений соответствующего фильтра [true, false, true] и т. д. Затем просто верните элемент обратного массива, если он включен в переменную фильтров false

const products = [
    { id: 1, size: 'S', color: 'blue', type: 'dress' },
    { id: 2, size: 'L', color: 'red', type: 'dress' },
    { id: 3, size: 'S', color: 'red', type: 'dress' },
    { id: 4, size: 'L', color: 'green', type: 'shirt' },
  ]

const filter1 = { size: 'S', color: 'red' }

const filter2 = { size: 'S' }

const filter3 = { size: 'S', color: 'red', type: 'dress' }

const remove = (products, filter) => {
    return products.filter(product => {
        const filters = Object.keys(filter).map(prop => {
            return filter[prop] === product[prop]
        })
        return filters.includes(false)
    })
}

const result1 = remove(products, filter1)
const result2 = remove(products, filter2)
const result3 = remove(products, filter3)

console.info(result1)
console.info(result2)
console.info(result3)

В remove(products, { size: 'S', color: 'red', type: 'dress' })type = dress следует игнорировать, так как ключ не существует. Но размер и цвет должны работать. В вашем коде type = dress изменяет предыдущее поведение размера и цвета. remove(products, { type: 'dress' }) не должен ничего фильтровать

eakl 08.04.2023 09:36

Я думаю, что вы правы, ключом к решению вашей проблемы является правильная реализация функции, которая может решить, следует ли удалить или сохранить элемент на основе переданных значений ключа, и которая должна иметь возможность динамически обрабатывать ваши требования.

Вот одно предложение по этому поводу:

const shouldkeep = kvs => obj => {
  for (const k in kvs)
    if (k in obj && obj[k] !== kvs[k]) 
      return true
  return false
}
const remove = (array, filter) => array.filter(shouldkeep(filter))

const products = [
  { size: 'S', color: 'blue' },
  { size: 'L', color: 'red' },
  { size: 'S', color: 'red' },
  { size: 'L', color: 'green' },
] 

console.info(remove(products, { size: 'S', color: 'red' }))
console.info(remove(products, { size: 'S' }))
console.info(remove(products, { size: 'S', color: 'red', type: 'dress' }))

Несколько замечаний по поводу этой реализации:

  • идея функции shouldkeep заключается в том, что она перебирает ключи вашего объекта фильтра и возвращает true (что означает «сохранять») только в том случае, если она проходит через все ключи без полностью совпадающих значений.
  • этот синтаксис shouldkeep = kvs => obj => может показаться странным, но на самом деле он очень полезен. Это называется каррированием и означает, что вы можете применить к функции один аргумент и получить функцию, которая ожидает следующий аргумент. При этом вы можете сделать что-то вроде products, {size: 'S'}), и он вернет функцию, которую вы можете использовать в качестве параметра для filter. Аккуратный!

remove(products, { type: 'dress' }) удаляет все, что не должно

eakl 08.04.2023 09:31

Другие вопросы по теме