与.filter()的AND / OR逻辑

时间:2017-03-14 21:24:50

标签: javascript arrays ecmascript-6 filtering

我正在尝试创建产品网格过滤系统。通过在JSON对象上调用.filter(),我得到了我正在寻找的结果。

const filteredProducts = allProducts.filter((a) => {
  // return brown or blue products in with omnis tag
  const prodTags = a.tags;
  return (
    prodTags.includes('brown') && prodTags.includes('single-eye') && prodTags.includes('happy') ||
    prodTags.includes('brown') && prodTags.includes('single-eye') && prodTags.includes('angry') ||
    prodTags.includes('brown') && prodTags.includes('two-eyes') && prodTags.includes('happy') ||
    prodTags.includes('brown') && prodTags.includes('two-eyes') && prodTags.includes('angry') ||
    prodTags.includes('blue') && prodTags.includes('single-eye') && prodTags.includes('happy') ||
    prodTags.includes('blue') && prodTags.includes('single-eye') && prodTags.includes('angry') ||
    prodTags.includes('blue') && prodTags.includes('two-eyes') && prodTags.includes('happy') ||
    prodTags.includes('blue') && prodTags.includes('two-eyes') && prodTags.includes('angry')
  );
});

我无法想出一种让这种动态变化的方法。我似乎无法创建一个可以为任意数量的标签自动生成此逻辑的函数。

我有一个看起来像这样的过滤系统(〜是当前选择的过滤系统):

-----------
Colors:
-----------
~ brown
gray
~ blue
pink


-----------
Eyes:
-----------
~ single-eye
~ two-eyes


-----------
Emotion:
-----------
~ happy
~ angry
sad

类别之间的逻辑是AND。类别值之间的逻辑是OR。我有一个功能设置,可以创建一个笛卡尔积数组。选定的过滤器数组如下所示:

[
    ['brown', 'single-eye', 'angry'],
    ['brown', 'single-eye', 'happy'],
    ['brown', 'two-eyes', 'angry'],
    ['brown', 'two-eyes', 'happy'],
    ['blue', 'single-eye', 'angry'],
    ['blue', 'single-eye', 'happy'],
    ['blue', 'two-eyes', 'angry'],
    ['blue', 'two-eyes', 'happy']
]

这是我被困的地方。我似乎无法找到一种在.filter()内动态集成这个生成的数组并使用||的方法和&&相应

非常感谢任何帮助。

4 个答案:

答案 0 :(得分:3)

其他答案看起来都是正确的。除了已经建议的内容之外,我还会使用Array.every,以便函数不依赖于每行的长度。

const cart = [
    ['brown', 'single-eye', 'angry'],
    ['brown', 'single-eye', 'happy'],
    ['brown', 'two-eyes', 'angry'],
    ['brown', 'two-eyes', 'happy'],
    ['blue', 'single-eye', 'angry'],
    ['blue', 'single-eye', 'happy'],
    ['blue', 'two-eyes', 'angry'],
    ['blue', 'two-eyes', 'happy']
  ];

const filteredProducts = allProducts.filter((a) => {
  const prodTags = a.tags;

  return cart.some((row) => {
    return row.every((element) => {
      return prodTags.includes(element);
    });
  });
});

答案 1 :(得分:2)

您可以在笛卡尔积产品数组上使用Array.prototype.some(),以确保满足至少一个条件:

const filteredProducts = allProducts.filter((a) => {
  const prodTags = a.tags,
        cart = [
                ['brown', 'single-eye', 'angry'],
                ['brown', 'single-eye', 'happy'],
                ['brown', 'two-eyes', 'angry'],
                ['brown', 'two-eyes', 'happy'],
                ['blue', 'single-eye', 'angry'],
                ['blue', 'single-eye', 'happy'],
                ['blue', 'two-eyes', 'angry'],
                ['blue', 'two-eyes', 'happy']
               ];

  return cart.some((e) => {
    return progTags.includes(e[0]) && progTags.includes(e[1]) && progTags.includes(e[2]);
  });
});

答案 2 :(得分:0)

预期生成的逻辑意味着数组中的任何特定行(如果生成true)将是需要计算的最后一行。我的方法是做一个for循环,当某个特定行返回true时该循环中断。如果true没有行,则回退到false

var filtersArray = [
  ['brown', 'single-eye', 'angry'],
  ['brown', 'single-eye', 'happy'],
  ['brown', 'two-eyes', 'angry'],
  ['brown', 'two-eyes', 'happy'],
  ['blue', 'single-eye', 'angry'],
  ['blue', 'single-eye', 'happy'],
  ['blue', 'two-eyes', 'angry'],
  ['blue', 'two-eyes', 'happy']
];


const filteredProducts = allProducts.filter((a) => {
  // return brown or blue products in with omnis tag
  const prodTags = a.tags;

  for (var i = 0; i < filtersArray.length; i++) {
    let color = filtersArray[i][0];
    let count = filtersArray[i][1];
    let emotion = filtersArray[i][2];

    if (prodTags.includes(color) && prodTags.includes(count) && prodTags.includes(emotion)) {
      return true;
    }
  }

  return false;
)};

答案 3 :(得分:0)

您可以使用带有分组项目的数组,并使用支票进行迭代。

var allProducts = [{ foo: 1, tags: ['abc', 'def'] }, { foo: 2, tags: ['blue', 'two-eyes', 'happy'] }],
    groups = [['brown', 'blue'], ['single-eye', 'two-eyes'], ['angry', 'happy']],
    filteredProducts = allProducts.filter(product => groups.every(group => group.some(item => product.tags.includes(item))));

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