【问题标题】: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 时)仍在显示。

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

【问题讨论】:

    标签: javascript arrays vue.js filter


    【解决方案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
    猜你喜欢
    • 2018-12-25
    • 2017-03-19
    • 2018-07-06
    • 1970-01-01
    • 2016-05-12
    • 2020-02-29
    • 1970-01-01
    • 2021-04-19
    • 2017-05-25
    相关资源
    最近更新 更多