javascript 如何使用filter对象从数组中删除元素

nbewdwxp  于 2023-04-10  发布在  Java
关注(0)|答案(4)|浏览(221)

我想在给定一个filter对象的情况下过滤一个数组

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.log(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.log(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.log(filteredProducts1)
/*
[
  { size: 'S', color: 'blue' },
  { size: 'L', color: 'red' },
  { size: 'L', color: 'green' },
]
*/

我的问题是从过滤器对象构建动态条件
我想改变信仰

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

进入

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

cedebl8k1#

你可以使用some来返回true,如果至少有一个条件存在并且不等于filter。
你甚至可以使用x[k]来代替x.hasOwnProperty(k),如果它保证有一些键指向的值是假值(undefinednull0..,'')。
另外,如果您的环境(浏览器/节点)支持Object.hasOwn,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.log(remove(products, { size: 'S', color: 'red' }))
console.log(remove(products, { size: 'S' }))
console.log(remove(products, { size: 'S', color: 'red', type: 'dress' }))
.as-console-wrapper { max-height: 100% !important; top: 0; }

edit修复问题

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.log(remove(products, { size: 'S', color: 'red' }))
console.log(remove(products, { size: 'S' }))
console.log(remove(products, { size: 'S', color: 'red', type: 'dress' }))
console.log(remove(products, { type: 'dress' }))
console.log(remove(products, {}))
.as-console-wrapper { max-height: 100% !important; top: 0; }
mzmfm0qo

mzmfm0qo2#

您可以确定过滤器中的任何键值对是否存在于数组中的每个对象中:

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.log(remove(products, { size: "S", color: "red" }));
// [ { size: "M", color: "blue" }, { size: "L", color: "green" } ]

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

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

ocebsuys3#

这个怎么样,变量过滤器将返回匹配过滤器[真,假,真]等布尔值的数组,然后只要返回数组项,如果包含在过滤器变量假

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.log(result1)
console.log(result2)
console.log(result3)
ttygqcqt

ttygqcqt4#

我认为你是正确的,解决问题的关键是正确地实现一个函数,它可以根据传递的键值来决定是否应该删除或保留一个项,并且应该能够动态地处理你的需求。
这里有一个建议:

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.log(remove(products, { size: 'S', color: 'red' }))
console.log(remove(products, { size: 'S' }))
console.log(remove(products, { size: 'S', color: 'red', type: 'dress' }))

关于此实现的一些注意事项:

  • 函数shouldkeep的思想是,它迭代过滤器对象的键,只有当它遍历所有键而没有完全匹配的值时,才返回true(这意味着“保持”)
  • 这个语法shouldkeep = kvs => obj =>可能看起来很奇怪,但它实际上非常有用。它被称为 currying,意味着你可以将一个参数应用于函数,并返回一个需要下一个参数的函数。有了这个,你可以做类似products, {size: 'S'})的事情,它返回一个函数,你可以将其用作filter的参数。整洁!

相关问题