【问题标题】:Filter JS multidimensional array过滤JS多维数组
【发布时间】:2018-09-20 15:25:15
【问题描述】:

我正在尝试过滤一些事件及其相应的时间段。数据结构是这样的:

var items = [
  {
    title: 'Category Title',
    events: [
      {
        title : '1:00pm',
        category : 1
      },
      {
        title: '2:00pm',
        category : 2
      }
    ]
  },
  {
    title: 'Category Title 2',
    events: [
      {
        title : '3:00pm',
        category : 1
      },
      {
        title: '4:00pm',
        category : 2
      }
    ]
  }
];

我想按类别过滤事件。我试过使用过滤器/地图,但似乎无法弄清楚。例如,如何过滤列表以仅返回类别为 1 的项目?

【问题讨论】:

  • 使用Array.prototype.some() 搜索匹配的类别。
  • underscore.js和lodash中也有好用的功能。
  • 您要过滤数组events或父数组items哪些数组事件包含category === 1
  • @Ele 我正在尝试返回所有事件及其父标题,其中各个事件类别 === 1。
  • 你能发布想要的输出吗?

标签: javascript arrays dictionary filter


【解决方案1】:

您可以使用函数filter 和函数some 来获取数组events 中具有特定类别的那些项目。

这个例子有一个项目,它的事件数组包含一个category === 3

var items = [  {    title: 'Category Title',    events: [      {        title : '1:00pm',        category : 1      },      {        title: '2:00pm',        category : 2      }    ]  },  {    title: 'Category Title 2',    events: [      {        title : '3:00pm',        category : 1      },      {        title: '4:00pm',        category : 2      }    ]  },  {    title: 'Category Title 3',    events: [      {        title : '3:00pm',        category : 1      },      {        title: '4:00pm',        category : 3      }    ]  }],
    cat = 3,
    result = items.filter(o => o.events.some(({category}) => cat === category));

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

如果您只需要获取带有category === 3 的事件,请使用函数reduce

var items = [  {    title: 'Category Title',    events: [      {        title : '1:00pm',        category : 1      },      {        title: '2:00pm',        category : 2      }    ]  },  {    title: 'Category Title 2',    events: [      {        title : '3:00pm',        category : 1      },      {        title: '4:00pm',        category : 2      }    ]  },  {    title: 'Category Title 3',    events: [      {        title : '3:00pm',        category : 1      },      {        title: '4:00pm',        category : 3      }    ]  }],
    cat = 3,
    result = items.reduce((a/*Accumulator*/, o/*Current object in array*/) => { 
      // 1. We get the events with a specific category  (In this case -> 3)
      var filtered = o.events.filter(({category}) => cat === category);
      
      // 2. If the previous filter returns at least one event, we need to push
      //    the current object 'o' with the filtered events.
      if (filtered.length) { // if length !== 0 we need to push the object.
        // 3. We use Object.assign to avoid any mutation over the original object.
        //    So, basically we create a new object with the original properties
        //    and finally we assign the filtered events to the property events.
        a.push(Object.assign({}, o, {events: filtered}));
      }
      
      return a;
    }, []/*Initial value (this array will contain the filtered objects)*/);

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

【讨论】:

  • 这绝对是朝着正确方向迈出的一步。现在,我想知道是否有办法只返回类别为 3 的实际事件项。现在,如果有匹配项,它会返回父项及其所有子项。我应该再次过滤它吗?
  • @GrantVinson 你想要与只有类别 === 3 的数组事件相同的输出吗?例如:[ { "title": "Category Title 3", "events": [ { "title": "4:00pm", "category": 3 } ] } ]
  • 是的,我只是想拉回父级和只有其具有 3 类别的子级。非常感谢您的帮助。
  • 你是一个真正的英雄。感谢您的帮助。我现在已经能够将多个过滤器链接在一起,以便为事件类别及其子事件列表提供更强大的过滤器。接受!
  • 您能解释一下减少/推送到“a”数组的情况吗?
【解决方案2】:

您应该在这里做的是使用 Array.filter() method 过滤您的 items 数组,基于子 events 数组,您可以使用 Array.some() 对其进行测试 找到category===1 的人。

var filteredResults = items.filter(function(item) {
  return item.events.some(e => e.category === 1);
});

演示:

var items = [{
    title: 'Category Title',
    events: [{
        title: '1:00pm',
        category: 1
      },
      {
        title: '2:00pm',
        category: 2
      }
    ]
  },
  {
    title: 'Category Title 2',
    events: [{
        title: '3:00pm',
        category: 1
      },
      {
        title: '4:00pm',
        category: 2
      }
    ]
  }
];

var result = items.filter(function(item) {
  return item.events.some(e => e.category === 1);
});


console.log(result);

【讨论】:

    【解决方案3】:

    您可以使用过滤器来获取精简列表,但您可以通过其他方式(例如 reduce)来实现。

    https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/filter

    var items = [
      {
        title: 'Category Title',
        events: [
          {
            title : '1:00pm',
            category : 1
          },
          {
            title: '2:00pm',
            category : 2
          }
        ]
      },
      {
        title: 'Category Title 2',
        events: [
          {
            title : '3:00pm',
            category : 1
          },
          {
            title: '4:00pm',
            category : 2
          }
        ]
      }
    ];
    let cat1, cat2;
    items.forEach(item => {
      cat1 = item.events.filter(item => item.category === 1)
      cat2 = item.events.filter(item => item.category === 2)
    })
    
    
    console.log(cat1, cat2)

    这里更高级一点,你可以给函数一个你想要的类别数组,它会返回一个对象,其中包含所有类别的键和其中的事件。希望这可以帮助。

    var items = [
          {
            title: 'Category Title',
            events: [
              {
                title : '1:00pm',
                category : 1
              },
              {
                title: '2:00pm',
                category : 2
              }
            ]
          },
          {
            title: 'Category Title 2',
            events: [
              {
                title : '3:00pm',
                category : 1
              },
              {
                title: '4:00pm',
                category : 2
              }
            ]
          }
        ];
        
        function filter(cat, arr) {
          return arr.filter(i => i.category === cat);
        }
        function getCategorys(category) {
          return items.reduce((prev, curr) => {
             category.forEach(cat => {
             !prev[cat] ? prev[cat] = [] : null;
             prev[cat] = [...filter(cat, curr.events), ...prev[cat]];
             })
             return prev;
          }, {})
        }
        
        console.log(getCategorys([1,2]))

    【讨论】:

      【解决方案4】:

      您可以使用以下函数来获得所需的结果:

      https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/Reduce https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/filter

      function filterByCategory(items, category) {
          return items.reduce((events, i) => {
              const filteredEvents = i.events.filter(e => e.category === category);
              if (filteredEvents) {
                  return events.concat(filteredEvents);
              }
              return events;
          }, []);
      }
      

      【讨论】:

        【解决方案5】:
        function hasCategory(item, cat) {
            for(e in item.events){
            if(item.events[e].category === cat) {
               return true;
             break;
            }
           }
           return false;
        }
        
        var filtered = items.filter((item) => {
            return hasCategory(item, 2);
        });
        
        console.log(filtered);
        

        【讨论】:

        • 谢谢@SamuelLiew,我不经常回答,我会更好地了解如何更好地做出贡献。
        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2013-06-09
        • 2020-04-10
        • 2021-05-24
        • 1970-01-01
        相关资源
        最近更新 更多