根据来自不同对象数组的属性和值过滤对象数组

Posted

技术标签:

【中文标题】根据来自不同对象数组的属性和值过滤对象数组【英文标题】:Filter an array of objects based on a property and value from a different array of objects 【发布时间】:2020-01-10 16:44:23 【问题描述】:

我有两组数组,一组用于表的标题(列),另一组用于表的行。

const headers = [
  
    text: 'Dessert (100g serving)',
    align: 'left',
    sortable: false,
    value: 'name',
    visible: true
  ,
   text: 'Calories', value: 'calories', visible: true ,
   text: 'Fat (g)', value: 'fat', visible: true ,
   text: 'Carbs (g)', value: 'carbs', visible: true ,
   text: 'Protein (g)', value: 'protein', visible: true ,
   text: 'Iron (%)', value: 'iron', visible: true 
]

const desserts = [
  
    name: 'Frozen Yogurt',
    calories: 159,
    fat: 6.0,
    carbs: 24,
    protein: 4.0,
    iron: '1%'
  ,
  
    name: 'Ice cream sandwich',
    calories: 237,
    fat: 9.0,
    carbs: 37,
    protein: 4.3,
    iron: '1%'
  ,
  
    name: 'Eclair',
    calories: 262,
    fat: 16.0,
    carbs: 23,
    protein: 6.0,
    iron: '7%'
  ,
  
    name: 'Cupcake',
    calories: 305,
    fat: 3.7,
    carbs: 67,
    protein: 4.3,
    iron: '8%'
  
]

我想要实现的是让用户能够决定他们希望在表格中查看哪些数据列。

我使用的是 Vue.js,所以我尝试设置一组复选框,每个复选框都是 v-bind 作为 headers 集合的标题。

我正在使用以下方法进行此操作:

computed: 
  filteredHeaders () 
    return this.headers.filter(header => header.visible)
  

这按预期工作,糟糕!表格列标题会根据复选框选择的列而变化。

我遇到的问题是尝试根据所选列(或 filteredHeaders)过滤行数据(或 desserts)。

我尝试了以下方法:

computed: 
  ...
  filteredItems () 
    return this.desserts.filter(dessert => 
      return this.filteredHeaders.some(header => 
        return Object.keys(header).some(prop => 
          return dessert[prop] != header[prop] && header.visible
        )
      )
    )
  

即使没有抛出错误,filteredItems 的结果仍然是原始desserts 的结果以及应排除的属性(当visible 被复选框集合设置为false 时)仍在显示。

我确定我很接近,但接近不会让我得到那支雪茄(俗话说)!

【问题讨论】:

【参考方案1】:

这个方法应该能大致达到你想要的效果:

const headers = [
    text: "Dessert (100g serving)",
    align: "left",
    sortable: false,
    value: "name",
    visible: true
  ,
  
    text: "Calories",
    value: "calories",
    visible: true
  ,
  
    text: "Fat (g)",
    value: "fat",
    visible: true
  ,
  
    text: "Carbs (g)",
    value: "carbs",
    visible: true
  ,
  
    text: "Protein (g)",
    value: "protein",
    visible: true
  ,
  
    text: "Iron (%)",
    value: "iron",
    visible: true
  
];

const desserts = [
    name: "Frozen Yogurt",
    calories: 159,
    fat: 6.0,
    carbs: 24,
    protein: 4.0,
    iron: "1%"
  ,
  
    name: "Ice cream sandwich",
    calories: 237,
    fat: 9.0,
    carbs: 37,
    protein: 4.3,
    iron: "1%"
  ,
  
    name: "Eclair",
    calories: 262,
    fat: 16.0,
    carbs: 23,
    protein: 6.0,
    iron: "7%"
  ,
  
    name: "Cupcake",
    calories: 305,
    fat: 3.7,
    carbs: 67,
    protein: 4.3,
    iron: "8%"
  
];

const filterRows = (rows, headers) => 
  // Map over the full list of rows to filter down
  return rows.map(row => 
    // Create a new row to return to avoid mutating
    const filteredRow = ;
    // Loop through each header and copy the row value corresponding to that header value
    headers.forEach(header => 
      filteredRow[header.value] = row[header.value];
    );
    // Return the copied and filtered row
    return filteredRow;
  );
;

console.log(filterRows(desserts, headers));
console.log(filterRows(desserts, [
  text: "Iron (%)",
  value: "iron",
  visible: true
]));

【讨论】:

我会接受这个作为答案,因为它是最容易理解的。仅供参考,这是我对解决方案的实施 - CodePen

以上是关于根据来自不同对象数组的属性和值过滤对象数组的主要内容,如果未能解决你的问题,请参考以下文章

从数组中拆分出对象属性和值[重复]

如何根据属性过滤对象数组?

根据属性值用 lodash 过滤对象数组

JavaScript 根据属性值过滤对象数组

如何键入属性和值均来自其他类型的对象

三种方法实现为数组中的对象添加一个新的属性和值