【问题标题】:Filter by multiple keys and values, Javascript按多个键和值过滤,Javascript
【发布时间】:2017-06-16 13:22:12
【问题描述】:

我正在尝试制作过滤器。过滤器的数量会动态变化,键的数量可以不同,值的数量也可以不同。

这是数据的样子:

var data = [
{id: "123", color: "Red", model: "Tesla"}, 
{id: "124", color: "Black", model: "Honda"}, 
{id: "125", color: "Red", model: "Audi"}, 
{id: "126", color: "Blue", model: "Tesla"}]

过滤键是颜色和型号。但有时我只会按颜色或型号过滤,有时会同时按两者过滤。我想制作一个涵盖这两种情况的功能。此外,用户可以选择许多值(特斯拉、本田...)。

键可以只有颜色,也可以只有模型,或两者兼而有之。 值可能类似于:只有“Red”、“Red”和“Blue”,或“Red”和“Tesla”,或“Red”、“Blue”和“Tesla”……取决于用户选择。

我试过这个:

var filtered = [];
data.forEach(item => {
   filterByKey.forEach(key => {
      values.forEach(value => {
         if (item[key] === value) {
             filtered.push(item);
          }
       });
    });
  });

这里是JsFiddle

当我有一个过滤键时,我的循环运行良好,但当我有多个键时,它就无法正常运行。将键和值作为数组传递是个好主意吗?

请不要使用 jQuery,只有纯 JavaScript。

【问题讨论】:

    标签: javascript filter


    【解决方案1】:

    您可以将filter()every() 一起使用,并使用includes() 检查values 数组中具有当前键的当前对象的值是否退出

    var data = [{"id":"123","color":"Red","model":"Tesla"},{"id":"124","color":"Black","model":"Honda"},{"id":"125","color":"Red","model":"Audi"},{"id":"126","color":"Blue","model":"Tesla"}]
    
    var keys = ["color", 'model'];
    var values = ["Tesla", "Audi", "Red"];
    
    var result = data.filter(function(e) {
      return keys.every(function(a) {
        return values.includes(e[a])
      })
    })
    
    console.log(result);

    【讨论】:

    • 这正是我想要的!谢谢!
    • 嘿 Nenad,函数效果很好,但使用它我发现了一个我们错过的案例。这种情况是当值重复相同的值时。颜色和型号具有相同的价值。这是一个愚蠢的例子,但假设颜色是“红色”,模型也是“红色”。我是否应该将键和值作为对象一起传递?你有什么建议?谢谢!
    • 嘿,内纳德?你能帮帮我吗?
    • @snoopy25 我没有看到问题jsfiddle.net/Lg0wyt9u/2114 它会返回它。
    【解决方案2】:

    您可以将组合方法与保持条件的 seach 对象结合使用,例如

    { 
        model: 'Tesla',                                    // a single value
        color: ['red', 'blue'],                            // a some value
        price: {                                           // a range/interval
            min: 2000, 
            max: 3000
        },
        transmission: v => v.toLowerCase() === 'automatic' // a function
    }
    

    var useConditions = search => a => Object.keys(search).every(k => 
            a[k] === search[k] ||
            Array.isArray(search[k]) && search[k].includes(a[k]) ||
            typeof search[k] === 'object' && +search[k].min <= a[k] &&  a[k] <= +search[k].max ||
            typeof search[k] === 'function' && search[k](a[k])
        ),
        data = [{ id: "123", color: "Red", model: "Tesla" }, { id: "124", color: "Black", model: "Honda" }, { id: "125", color: "Red", model: "Audi" }, { id: "126", color: "Blue", model: "Tesla" }],
        filters = { color: ['Red', 'Blue'], model: 'Tesla' };
    
    console.log(data.filter(useConditions(filters)));

    【讨论】:

    • 这应该是公认的答案,简单而神奇!谢谢
    【解决方案3】:

    您可以使用Array.prototype.filter(),其中测试数组每个元素的函数是:

    el =&gt; !!filterBy.toString().match(new RegExp(`(?=.*${el.color})(?=.*${el.model})`))

    它由一个正则表达式 new RegExp(`(?=.*${el.color})(?=.*${el.model})`)) 组成,它与另一个字符串 filterBy.toString() 中的字符串 colormodel 匹配

    var data = [{id: "123", color: "Red", model: "Tesla"}, {id: "124", color: "Black", model: "Honda"}, {id: "125", color: "Red", model: "Audi"}, {id: "126", color: "Blue", model: "Tesla"}],
        filterBy = ['Tesla', 'Audi', 'Red', 'Black'],
        result = data.filter(el => !!filterBy.toString().match(new RegExp(`(?=.*${el.color})(?=.*${el.model})`)));
    
    console.log(result);

    此外,您还可以组合Array.prototype.filter()Array.prototype.includes()

    var data = [{id: "123", color: "Red", model: "Tesla"}, {id: "124", color: "Black", model: "Honda"}, {id: "125", color: "Red", model: "Audi"}, {id: "126", color: "Blue", model: "Tesla"}],
        filterBy = ['Tesla', 'Audi', 'Red', 'Black'],
        result = data.filter(el => filterBy.includes(el.model) && filterBy.includes(el.color));
    
    console.log(result);

    【讨论】:

      【解决方案4】:

      对于这样的情况,我就是这样做的:

      function _filter(data, query) { // query = "Red" or "Tesla"
          return data.filter(el => {
              return el.model.toLowerCase().indexOf(query.toLowerCase()) !== -1 ||
              el.name.toLowerCase().indexOf(query.toLowerCase()) !== -1;
          });
      }
      

      现在这个函数搜索模型键和名称键的数据。

      【讨论】:

        【解决方案5】:

        这是你想要达到的目标吗?

        var data = [
          {id: "123", color: "Red", model: "Tesla"}, 
          {id: "124", color: "Black", model: "Honda"}, 
          {id: "125", color: "Red", model: "Audi"}, 
          {id: "126", color: "Blue", model: "Tesla"}
        ];
        
        var allowedColors = ["Red", "Blue"];
        var allowedModels = ["Tesla", "Audi"];
        
        function filter (cars, colors, models) {
          return cars.filter(function (car) {
            return colors.indexOf(car.color) !== -1 && // check if the car's color is allowed
              models.indexOf(car.model) !== -1;        // check if the car's model is allowed
          });
        }
        
        var filtered = filter(data, allowedColors, allowedModels);
        console.log(filtered);

        【讨论】:

        • 我认为他可能希望能够将模型或颜色设置为空,意思是“全部”。
        • 这仅适用于这种情况,但如果我想只对颜色或模型进行分组过滤,这不起作用。
        【解决方案6】:

        过滤是 JS 原生的,试试这个:

        data.filter(item => item.color==='Red');
        // or in the old fashion 
        data.filter(function(item){ return item.color==='Red';} );
        

        【讨论】:

          【解决方案7】:

          在这里,我有一个不同的场景。

          我有一个对象

          d={r1: {name: "r1", validation: true}, r2: {name: "r2", validation: true}};
          

          还有另一个数组

          a = ["r1"];
          

          这里,我想要的结果是

          d={r1: {name: "r1", validation: true}}
          

          【讨论】:

            【解决方案8】:

            使用filter() 过滤数据,结合some() 使用includes() 检查多个keys 是否匹配至少一个来自values 的字符串

            // array --------------------
            
            const data = [
              { id: '123', color: 'Red', model: 'Tesla' },
              { id: '124', color: 'Black', model: 'Honda' },
              { id: '125', color: 'Red', model: 'Audi' },
              { id: '126', color: 'Blue', model: 'Tesla' },
            ];
            
            
            
            // filter exact match --------------------
            
            const keysExact = ['color', 'model'];
            const valuesExact = ['Tesla', 'Audi', 'Red'];
            
            const resultExact = data.filter((item) =>
              keysExact.every((a) => valuesExact.includes(item[a]))
            );
            
            console.log(resultExact);
            // result:
            // [
            //   { id: '123', color: 'Red', model: 'Tesla' },
            //   { id: '125', color: 'Red', model: 'Audi' },
            // ]; 
            

            使用filter() 过滤数据,结合some() 使用includes() 检查多个keys 是否包含至少一个来自values 的字符串。

            // array --------------------
            
            const data = [
              { id: '123', color: 'Red', model: 'Tesla' },
              { id: '124', color: 'Black', model: 'Honda' },
              { id: '125', color: 'Red', model: 'Audi' },
              { id: '126', color: 'Blue', model: 'Tesla' },
            ];
            
            
            
            // filter data by keys containing values string (at least one of the string in values) --------------------
            
            const keysSome = ['color', 'model'];
            const valuesSome = ['Tes', 're'];
            
            const resultSome = data.filter((item) =>
              keysSome.some((key) =>
                valuesSome.some((val) => item[key].toLowerCase().includes(val.toLowerCase()))
              )
            );
            
            console.log(resultSome);
            // result:
            // [
            //   { id: '123', color: 'Red', model: 'Tesla' },
            //   { id: '125', color: 'Red', model: 'Audi' },
            //   { id: '126', color: 'Blue', model: 'Tesla' },
            // ];
            

            使用filter()过滤数据,结合every()检查多个keys是否包含来自values所有字符串,使用includes()

            // array --------------------
            
            const data = [
              { id: '123', color: 'Red', model: 'Tesla' },
              { id: '124', color: 'Black', model: 'Honda' },
              { id: '125', color: 'Red', model: 'Audi' },
              { id: '126', color: 'Blue', model: 'Tesla' },
            ];
            
            
            
            // filter data by keys containing values string (matches all strings from values) --------------------
            
            const keysEvery = ['color', 'model'];
            const valuesEvery = ['Tes', 're'];
            
            const resultEvery = data.filter((item) =>
              keysEvery.every((key) =>
                valuesEvery.some((val) => item[key].toLowerCase().includes(val.toLowerCase()))
              )
            );
            
            console.log(resultEvery);
            // result:
            // [
            //   { id: '123', color: 'Red', model: 'Tesla' }
            // ]
            

            【讨论】:

            • 您是否使用特定网站来获得这些视觉搜索结果?
            • 我实际上是在 Figma 中设计的,因为我也是一名设计师。
            猜你喜欢
            • 1970-01-01
            • 2021-08-26
            • 1970-01-01
            • 2020-07-31
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            相关资源
            最近更新 更多