如何使用Lodash或纯javascript使用动态过滤器过滤嵌套对象?

如何使用Lodash或纯javascript使用动态过滤器过滤嵌套对象?,javascript,Javascript,我有以下数据: const products = [{ name: "Product 1", options: [ { id: 1, optionName: "Color", value: "Red" }, { id: 2, optionName: "Size", value: "Small" } ]}, { name:

我有以下数据:

const products = [{
 name: "Product 1",
 options: [
  {
    id: 1,
    optionName: "Color",
    value: "Red" 
  },
  { 
    id: 2,
    optionName: "Size",
    value: "Small" 
  }
 ]},
{
 name: "Product 2",
 options: [
  {
    id: 1,
    optionName: "Color",
    value: "Red" 
  },
  { 
    id: 2,
    optionName: "Size",
    value: "Large" 
  }
 ]}];
我有一个过滤器对象,它是动态创建的:

let selectedFilters = {"Color":"Red", "Size":"Small"};
我只想获得满足selectedFilters对象中指定的所有条件的产品。在这个例子中,我应该只得到“产品1”

这是我迄今为止尝试过的,但这些工作都不是我所需要的:

let filteredProducts = [];
let keys = Object.keys(selectedFilters);
keys.forEach(function(filterKey) {
  let f = _.filter(products, function(o) {
    let flag = false;
    let searchFilterKey = selectedFilters[filterKey];
    let index = o.options.findIndex(o=> o.optionName == filterKey && o.value == searchFilterKey);
    if (index > 0)
      return o;
  });
  filteredProducts = f;
});

您可以获取数组中过滤器的值,并使用匹配条件运行each函数。由于“value”是此处的重要属性,因此请使用它对selectedFilters运行其值

如果密钥是标准的一部分,请对其执行相同的操作

const产品=[{
名称:“产品1”,
选项:[{
id:1,
选项名称:“颜色”,
值:“红色”
},
{
id:2,
选项名称:“大小”,
价值:“小”
}
]
},
{
名称:“产品2”,
选项:[{
id:1,
选项名称:“颜色”,
值:“红色”
},
{
id:2,
选项名称:“大小”,
值:“大”
}
]
}
]
让selectedFilters={
“颜色”:“红色”,
“大小”:“小”
};
常量arrFilterValues=Object.values(selectedFilters);
const arrFilterKeys=Object.keys(selectedFilters);
const result=products.filter(x=>{
返回x.options.every(y=>arrFilterValues.includes(y['value'])&&arrFilterKeys.includes(y['optionName']))
})

console.log(result)
您可以根据对象的条目进行筛选

const产品=[{
名称:“产品1”,
选项:[
{
id:1,
选项名称:“颜色”,
值:“红色”
},
{ 
id:2,
选项名称:“大小”,
价值:“小”
}
]},
{
名称:“产品2”,
选项:[
{
id:1,
选项名称:“颜色”,
值:“红色”
},
{ 
id:2,
选项名称:“大小”,
值:“大”
}
]}];
让selectedFilters={“Color”:“Red”,“Size”:“Small”};
let entries=Object.entries(selectedFilters);
const res=products.filter({options})=>
每个([k,v])=>options.some(o=>o.optionName==k&&o.value==v));

控制台日志(res)您可以使用和获得结果。过滤器阵列可以动态扩展,无需对其进行排序或显示所有过滤器属性。

我对产品阵列进行过滤。这里有每个产品,这将被选中,过滤器阵列的所有过滤器都将被填满。对于每一个过滤器标准,我都会看看这个标准是否适用于该产品的一些选项。为此,有optionname和要匹配的值

函数myFilter(数组,过滤器){
返回数组.filter({options})=>
Object.entries(filters).every([key,value])=>
选项。一些((选项)=>
option.optionName==键和option.value==值
)
)
);
}
常数乘积=[{
名称:“产品1”,
选项:[
{
id:1,
选项名称:“颜色”,
值:“红色”
},
{ 
id:2,
选项名称:“大小”,
价值:“小”
}
]},
{
名称:“产品2”,
选项:[
{
id:1,
选项名称:“颜色”,
值:“红色”
},
{ 
id:2,
选项名称:“大小”,
值:“大”
}
]}];
让过滤器={“颜色”:“红色”,“大小”:“小”};
日志(myFilter(产品、过滤器))
您可以尝试使用,然后使用函数foreach
product.options
检查selectedFilters对象中是否存在它的属性

const products = [{
  name: "Product 1",
  options: [
    {
      id: 1,
      optionName: "Color",
      value: "Red" 
   },
   { 
      id: 2,
      optionName: "Size",
      value: "Small" 
   }
  ]
},
{
  name: "Product 2",
  options: [
    {
      id: 1,
      optionName: "Color",
      value: "Red" 
    },
    { 
      id: 2,
      optionName: "Size",
      value: "Large" 
    }
  ]
 }
];

let selectedFilters = {"Color":"Red", "Size":"Small"};

let filteredProducts = products.filter(product => {
    return product.options.every(({ optionName, value }) => !!selectedFilters[optionName] && selectedFilters[optionName] === value);
});

console.log(filteredProducts);

谢谢你的回答,我忘了说选项数组也是动态的。selectedFilters对象的属性数始终与选项数组的属性数相同。例如,如果我在选项数组中添加了一个名为“权重”的新选项,则selectedFilters必须具有一个名为“权重”的属性,该属性必须具有某个值。如果任何选项都可以共享值,即多个“是/否”选项,则该属性将得到边缘大小写,因为它不尊重必须包含目标值的选项名称
const products = [{
  name: "Product 1",
  options: [
    {
      id: 1,
      optionName: "Color",
      value: "Red" 
   },
   { 
      id: 2,
      optionName: "Size",
      value: "Small" 
   }
  ]
},
{
  name: "Product 2",
  options: [
    {
      id: 1,
      optionName: "Color",
      value: "Red" 
    },
    { 
      id: 2,
      optionName: "Size",
      value: "Large" 
    }
  ]
 }
];

let selectedFilters = {"Color":"Red", "Size":"Small"};

let filteredProducts = products.filter(product => {
    return product.options.every(({ optionName, value }) => !!selectedFilters[optionName] && selectedFilters[optionName] === value);
});

console.log(filteredProducts);