【问题标题】:How to filter an array on different conditions using ES2016?如何使用 ES2016 在不同条件下过滤数组?
【发布时间】:2018-11-29 14:07:54
【问题描述】:

在下面的 sn-p 中,我们需要根据不同的 AND , OR 条件过滤数组。 条件

  1. 如果过滤器对象的“isFiltered”为真,它应该过滤。
  2. PatternGroupCode "OTHER" 表示它包括除那些以外的所有面料 标记为“isFiltered”的面料为假。
  3. fabricColor 应用了相同的“OTHER”条件。

我可以使用 fabricColor id 进行过滤。但不能使用patternGroupCode。

// all products
let products = [
  { name: "A", fabricColorGroupCodes:["OTHER"], patternGroupCode: 'PLAID', size: 50 },
  { name: "B", fabricColorGroupCodes:["BLUE"], patternGroupCode: 'WINDOWPANE', size: 60 },
  { name: "C", fabricColorGroupCodes:["OTHER", "BLUE"], patternGroupCode: 'SOLID', size: 100 },
  { name: "D", fabricColorGroupCodes:["OTHER", "BLACK"], patternGroupCode: 'PLAID', size: 70 },
  { name: "E", fabricColorGroupCodes:["BLACK"], patternGroupCode: 'WINDOWPANE', size: 80 },
  { name: "F", fabricColorGroupCodes:["BLACK"], patternGroupCode: 'SOLID', size: 100 },
  { name: "G", fabricColorGroupCodes:["GREEN"], patternGroupCode: 'PLAID', size: 90 },
  { name: "H", fabricColorGroupCodes:["GREEN"], patternGroupCode: 'SOLID', size: 100 },
  { name: "I", fabricColorGroupCodes:["GREEN"], patternGroupCode: 'WINDOWPANE', size: 80 },
 { name: "J", fabricColorGroupCodes:["GREEN"], patternGroupCode: 'PAISLEY', size: 80 }
];

function multiFilter(array, filters) {
  return array.filter(d => ( 
    Object.entries(filters).every(([k ,v]) => (
      Object.values(v).map(m => m.id).includes(d[k].id) 
    )) 
  ));
}

// filter conditions
// here we choose OTHER so it will filter on color BLACK and GREEN and 
// omit the BLUE because isFilter tag is false, same for patternGroupCode.
// so here it filter on SOLID , PLAID and WINDOWPANE and will omit PAISLEY .
let filters = {
  fabricColor: [
    {"id": 'BLACK', "isFiltered": true}, 
    {"id": 'BLUE', "isFiltered": false},
    {"id": 'OTHER', "isFiltered": true}
  ], 
  patternGroupCode: [
    {"patternGroupCode": 'OTHER', "isFiltered": true}, 
    {"patternGroupCode": 'STRIPES', "isFiltered": false}, 
    {"patternGroupCode": 'PLAID', "isFiltered": true}, 
    {"patternGroupCode": 'PAISLEY', "isFiltered": false}, 
    {"patternGroupCode": 'SOLID', "isFiltered": true}
  ]
};

var filtered = multiFilter(products, filters);
console.log(filtered);

【问题讨论】:

  • 只是另一个问题,您能否将数据格式更改为对过滤器更友好的方式,即使用一对键/值对而不是高度特殊的名称或嵌套对象结构?
  • 顺便说一句,第二个,第三个,...过滤 AND 或 OR 条件?
  • 面料颜色和patternGroupCode有AND条件
  • 你能建议过滤器友好的数据格式,所以我会相应地更新
  • 要理解,代码中的当前过滤器意味着颜色不是蓝色且图案不是(条纹或佩斯利)?另外,过滤器中是否可能没有OTHER,如果是,预期的输出是什么?

标签: javascript arrays filter


【解决方案1】:

您可以使用reduce 在每个过滤器的迭代中过滤产品(从整个产品数组作为初始累加器开始,并在应用每个过滤器后返回过滤后的版本)。

此外,由于您愿意修改对象的结构,因此我继续进行了一些小的更改(从产品中的 fabricColor 键中删除 id 并将其添加到 patternGroupCode 过滤器对象中)只是为了保持一致。

function multiFilter(array, filters) {
  return Object.entries(filters).reduce((acc, [k, kFilters]) => {
    let isFiltered = new Set(kFilters.filter(f => f.isFiltered).map(f => f.id)),
      other = kFilters.some(f => f.id === 'OTHER' && f.isFiltered),
      notFiltered = new Set(kFilters.filter(f => !f.isFiltered).map(f => f.id));
    return acc.filter(p => other ? !notFiltered.has(p[k]) : isFiltered.has(p[k]));
  }, array);
}


let products = [{
    name: "A",
    fabricColor: 'BLUE',
    patternGroupCode: 'PLAID',
    size: 50
  },
  {
    name: "B",
    fabricColor: 'BLUE',
    patternGroupCode: 'WINDOWPANE',
    size: 60
  },
  {
    name: "C",
    fabricColor: 'BLUE',
    patternGroupCode: 'SOLID',
    size: 100
  },
  {
    name: "D",
    fabricColor: 'BLACK',
    patternGroupCode: 'PLAID',
    size: 70
  },
  {
    name: "E",
    fabricColor: 'BLACK',
    patternGroupCode: 'WINDOWPANE',
    size: 80
  },
  {
    name: "F",
    fabricColor: 'BLACK',
    patternGroupCode: 'SOLID',
    size: 100
  },
  {
    name: "G",
    fabricColor: 'GREEN',
    patternGroupCode: 'PLAID',
    size: 90
  },
  {
    name: "H",
    fabricColor: 'GREEN',
    patternGroupCode: 'SOLID',
    size: 100
  },
  {
    name: "I",
    fabricColor: 'GREEN',
    patternGroupCode: 'WINDOWPANE',
    size: 80
  },
  {
    name: "I",
    fabricColor: 'GREEN',
    patternGroupCode: 'PAISLEY',
    size: 80
  }
];

let filters = {
  fabricColor: [{
    "id": 'BLACK',
    "isFiltered": true
  }, {
    "id": 'BLUE',
    "isFiltered": false
  }, {
    "id": 'OTHER',
    "isFiltered": true
  }],
  patternGroupCode: [{
      "id": 'OTHER',
      "isFiltered": true
    },
    {
      "id": 'STRIPES',
      "isFiltered": false
    },
    {
      "id": 'PLAID',
      "isFiltered": true
    },
    {
      "id": 'PAISLEY',
      "isFiltered": false
    },
    {
      "id": 'SOLID',
      "isFiltered": true
    }
  ]
};

var filtered = multiFilter(products, filters);
console.log(filtered);

【讨论】:

  • 在我的场景模式组代码中,fabricColor 没有相同的过滤键,如 ID。所以我不能将 patternGroupCode 修改为 ID。
【解决方案2】:

我建议简化数据结构以使用更简化的过滤器和简化的过滤器对象。

function multiFilter(array, filters) {
    return array.filter(o =>
        Object
            .entries(filters)
            .every(([k, v]) => o[k] in v ? v[o[k]] : v.OTHER)
    );
}

var products = [
        { name: "A", fabricColor: 'BLUE', patternGroupCode: 'PLAID', size: 50 },
        { name: "B", fabricColor: 'BLUE', patternGroupCode: 'WINDOWPANE', size: 60 },
        { name: "C", fabricColor: 'BLUE', patternGroupCode: 'SOLID', size: 100 },
        { name: "D", fabricColor: 'BLACK', patternGroupCode: 'PLAID', size: 70 },
        { name: "E", fabricColor: 'BLACK', patternGroupCode: 'WINDOWPANE', size: 80 },
        { name: "F", fabricColor: 'BLACK', patternGroupCode: 'SOLID', size: 100 },
        { name: "G", fabricColor: 'GREEN', patternGroupCode: 'PLAID', size: 90 },
        { name: "H", fabricColor: 'GREEN', patternGroupCode: 'SOLID', size: 100 },
        { name: "I", fabricColor: 'GREEN', patternGroupCode: 'WINDOWPANE', size: 80 },
        { name: "I", fabricColor: 'GREEN', patternGroupCode: 'PAISLEY', size: 80 }
    ],
    filters = {
        fabricColor: { BLACK: true, BLUE: false, OTHER: true },
        patternGroupCode: { PLAID: true, SOLID: true, STRIPES: false, PAISLEY: false, OTHER: true }
    },
    filtered = multiFilter(products, filters);

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

【讨论】:

  • 我同意简单化数据结构。但是如果我们有复杂的数据和过滤器呢?
  • 对于更复杂的过滤,您可以查看here,例如。
【解决方案3】:

假设我们将过滤产品,例如按大小。


结构

let products = [
  { name: "A", fabricColor: {"id": 'BLUE'}, patternGroupCode: 'PLAID', size: 50 },
  { name: "B", fabricColor: {"id": 'BLUE'}, patternGroupCode: 'WINDOWPANE', size: 60 },
  { name: "C", fabricColor: {"id": 'BLUE'}, patternGroupCode: 'SOLID', size: 100 },
  { name: "D", fabricColor: {"id": 'BLACK'}, patternGroupCode: 'PLAID', size: 70 },
  { name: "E", fabricColor: {"id": 'BLACK'}, patternGroupCode: 'WINDOWPANE', size: 80 },
  { name: "F", fabricColor: {"id": 'BLACK'}, patternGroupCode: 'SOLID', size: 100 },
  { name: "G", fabricColor: {"id": 'GREEN'}, patternGroupCode: 'PLAID', size: 90 },
  { name: "H", fabricColor: {"id": 'GREEN'}, patternGroupCode: 'SOLID', size: 100 },
  { name: "I", fabricColor: {"id": 'GREEN'}, patternGroupCode: 'WINDOWPANE', size: 80 },
 { name: "J", fabricColor: {"id": 'GREEN'}, patternGroupCode: 'PAISLEY', size: 80 }
];

功能

const sizeAbove = value => o => o.size > value
const sizeBelow = value => o => o.size < value

products.filter(sizeAbove(90))
products.filter(sizeBelow(60))

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-08-29
    • 1970-01-01
    • 2010-12-02
    • 1970-01-01
    • 2020-12-31
    相关资源
    最近更新 更多