过滤两个对象数组

时间:2016-09-05 08:46:13

标签: javascript arrays

我有两个数组,我希望使用另一个数组的值过滤一个数组。因此,我有汽车阵列,我想通过具有过滤器阵列值的汽车进行过滤。我的代码如下:

let cars = [
  {name: "Audi", price: "1000", transmission: "Manual"},
  {name: "Golf", price: "2000", transmission: "Manual"},
  {name: "Passat", price: "3000", transmission: "Automatic"},
  {name: "Seat", price: "4000", transmission: "Manual"}
];

let filters = [
  {searchFilter : ["price", 2000, 3000]},
  {searchFilter : ["transmission", "", "automatic"]},
];

let carsToShow = "";

let result = cars.filter ( c => {
  let carsToShow = "";
  return filters.filter( f => {
    if(f.searchFilter[0] === "price"){
      carsToShow = c.price >= f.searchFilter[1] && c.price <= f.searchFilter[2]
    }

    if(f.searchFilter[0] === "transmission"){
      if(f.searchFilter[1] !== ""){
        carsToShow = c.transmission.toLowerCase() === "manual"
      } 

      if(f.searchFilter[2] !== ""){
        carsToShow = c.transmission.toLowerCase() === "automatic"
      } 
    }

    return carsToShow;
  })

})

console.log(result);

在这种情况下,结果应为{name: "Passat", price: "3000", transmission: "Automatic"}。但它没有用。

有什么建议吗?

3 个答案:

答案 0 :(得分:3)

您可以针对每种搜索条件使用Array#every

var cars = [{ name: "Audi", price: "1000", transmission: "Manual" }, { name: "Golf", price: "2000", transmission: "Manual" }, { name: "Passat", price: "3000", transmission: "Automatic" }, { name: "Seat", price: "4000", transmission: "Manual" }],
    filters = [{ searchFilter: ["price", 2000, 3000] }, { searchFilter: ["transmission", "", "automatic"] }],
    result = cars.filter(c =>
        filters.every(f => {
            if (f.searchFilter[0] === "price") {
                return c.price >= f.searchFilter[1] && c.price <= f.searchFilter[2]
            }
            if (f.searchFilter[0] === "transmission") {
                return c.transmission.toLowerCase() === f.searchFilter[1] || c.transmission.toLowerCase() === f.searchFilter[2];
            }
        }
    ));
    
console.log(result);

建议使用更简洁的数据结构来搜索对象,例如

{ 
    /* color: 'red', */                                // a single 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] ||
        typeof search[k] === 'object' && +search[k].min <= a[k] &&  a[k] <= +search[k].max ||
        typeof search[k] === 'function' && search[k](a[k])
    ),
    cars = [{ name: "Audi", price: "1000", transmission: "Manual" }, { name: "Golf", price: "2000", transmission: "Manual" }, { name: "Passat", price: "3000", transmission: "Automatic" }, { name: "Seat", price: "4000", transmission: "Manual" }],
    filters = { price: { min: 2000, max: 3000 }, transmission: v => v.toLowerCase() === 'automatic' };

console.log(cars.filter(useConditions(filters)));

答案 1 :(得分:2)

我要做的第一件事是构建filters中的条目,以便数组的[0]条目不特别:

let filters = [
  {filter: "price", values: [2000, 3000]},
  {filter: "transmission", values: ["", "automatic"]},
];

理想情况下,数据在使用price的数字或字符串方面是一致的,而不是在一个地方使用数字而在另一个地方使用字符串,但我会认为这是一个设计约束

然后,删除任何过滤条件不匹配的条目:对于每辆汽车,我们使用filters.some查找不匹配的过滤条目:

let result = cars.filter(c => !filters.some(f => {
  let value = c[f.filter].toLowerCase();
  return f.values.findIndex(v => v == value) == -1;
}));

实时复制:

&#13;
&#13;
let cars = [
    { name: "Audi",  price: "1000", transmission: "Manual" },
    { name: "Golf", price: "2000", transmission: "Manual" },
    { name: "Passat", price: "3000", transmission: "Automatic" },
    { name: "Seat", price: "4000", transmission: "Manual" }
];

let filters = [
  {filter: "price", values: [2000, 3000]},
  {filter: "transmission", values: ["", "automatic"]},
];

//let carsToShow = "";     <== This wasn't used for anything

let result = cars.filter(c => !filters.some(f => {
  let value = c[f.filter].toLowerCase();
  return f.values.findIndex(v => v == value) == -1;
}));

console.log(result);
&#13;
&#13;
&#13;

注意我在findIndex电话中使用宽松的相等(这就是为什么它不仅仅是indexOf),所以2000 == "2000"。但同样,理想情况下,数据和过滤器将具有相同的类型,因此我们可以使用

return f.values.inexOf(value) == -1;

代替。

答案 2 :(得分:0)

但如果您需要获得的数据多于一个......

<script>
"use strict"
let cars = [
  {name: "Audi", price: "1000", transmission: "Manual"},
  {name: "Golf", price: "2000", transmission: "Manual"},
  {name: "Passat", price: "3000", transmission: "Automatic"},
  {name: "Passat", price: "2500", transmission: "Automatic"},
  {name: "Seat", price: "4000", transmission: "Manual"}
];

let filters = [
  {searchFilter : ["price", 2000, 3000]},
  {searchFilter : ["transmission", "", "automatic"]},
];



let result = cars.filter ( c => {
  let carsToShow=false;
  let carsToShowtran = false;
  let carsToShowPrice = false;
 let re= filters.filter( f => { 
    if(f.searchFilter[0] === "price"){
      carsToShowPrice = c.price >= f.searchFilter[1] && c.price <= f.searchFilter[2]      
    }
    if(f.searchFilter[0] === "transmission"){
      if(f.searchFilter[1] !== ""){
        carsToShowtran = c.transmission.toLowerCase() === "manual"
      } 
      if(f.searchFilter[2] !== ""){
        carsToShowtran = c.transmission.toLowerCase() === "automatic"
      } 
    }
    if(carsToShowtran && carsToShowPrice){
        carsToShow=true;
    }   
    return carsToShow;
  })
  if(re.length!=0){
    return true;
  }

})

console.log(result);
</script>