【问题标题】:How do I filter an array based on the values of one of its nested arrays?如何根据其中一个嵌套数组的值过滤数组?
【发布时间】:2017-09-23 17:01:03
【问题描述】:

假设我有一个遵循以下模式的对象数组:

var posts = [
    {
        title: post_ab,
        category_array : [
            { id: 1, slug: category-a },
            { id: 2, slug: category-b }
        ]
    },
    {
        title: post_ac,
        category_array : [
            { id: 1, slug: category-a },
            { id: 3, slug: category-c }
        ]
    },
    {
        title: post_bc,
        category_array : [
            { id: 2, slug: category-b },
            { id: 3, slug: category-c }
        ]
    }
]

我正在尝试过滤上述数组,并且只返回 category_array 包含与指定值匹配的 slug 的值。

例如,如果我想过滤 'category-c',则只会返回第二个和第三个值(post_ac 和 post_bc)。

我尝试过使用嵌套过滤器,但这让我无处可去:

var currentCategory = 'category-b';

var filteredPosts = function( posts ) {
    return posts.filter( function( post ){
        return post.category_array.filter( function( category ){
            return category.slug === currentCategory;
        })
    })
}

【问题讨论】:

  • 将内部过滤器更改为Array#some,例如post.category_array.some 它应该可以正常工作。

标签: javascript arrays loops filter


【解决方案1】:

您可以创建一个Array.prototype.find() 来获取数组category_arrayslug 等于'category-b' 的第一个元素,如果存在则返回该元素将由@ 评估为真,如果不存在则为假987654322@:

var posts = [{title: 'post_ab',category_array : [{ id: 1, slug: 'category-a' },{ id: 2, slug: 'category-b' }]},{title: 'post_ac',category_array : [{ id: 1, slug: 'category-a' },{ id: 3, slug: 'category-c' }]},{title: 'post_bc',category_array : [{ id: 2, slug: 'category-b' },{ id: 3, slug: 'category-c' }]}],
    currentCategory = 'category-b',
    result = posts.filter(function (p) {
      // Return only the very first element found
      return p.category_array.find(function (c) {
        return currentCategory === c.slug;
      });
    });

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

【讨论】:

  • 谢谢 - 绝对更符合我的方法 - 但在其他一些答案中使用 Array.some 更优雅,IMO。
  • @YosvelQuintero 我没有投票赞成/反对票,对于小型数据集可能没关系,但是 filtering 两次将在不需要时将两个数据集迭代两次。 someindexOfincludes 只会迭代直到找到匹配项。
  • @CodingIntrigue 这是性能,因为另一个过滤器将遍历所有数组。同意!现在更新了使用Array.prototype.find() 的答案,它将返回找到的第一个元素。感谢您的评论
【解决方案2】:

用 some() 替换你的内部过滤器

【讨论】:

    【解决方案3】:

    让我们将somefilter 结合起来

    var posts = [
            {
                title: 'post_ab',
                category_array : [
                    { id: 1, slug: 'category-a' },
                    { id: 2, slug: 'category-b' }
                ]
            },
            {
                title: 'post_ac',
                category_array : [
                    { id: 1, slug: 'category-a' },
                    { id: 3, slug: 'category-c' }
                ]
            },
            {
                title: 'post_bc',
                category_array : [
                    { id: 2, slug: 'category-b' },
                    { id: 3, slug: 'category-c' }
                ]
            }
        ];
        var result = posts.filter(a => a.category_array.some(cat => cat.slug.includes('a')));
        console.log(result);

    【讨论】:

    • 使用箭头函数会使那些return 语句有点多余。 posts.filter(a => a.category_array.some(cat => cat.slug.includes('a')))。否则,看起来不错。
    【解决方案4】:

    你必须在内循环中使用Array.prototype.some()

    var filteredPosts = function(posts) {
        return posts.filter(function(post){
            return post["category_array"].some(function(category){
                return category.slug === currentCategory;
            });
        });
    }
    

    它将返回一个boolean 结果,可以在.filter() 回调中使用。

    【讨论】:

    • 搞定 - 谢谢。虽然上面的例子给出了一个语法错误(我的错是没有把标题用引号括起来)。
    • 不客气。是的,这是 JS 数组中的错误。
    • 接受,因为它坚持我过时的 JS 语法。
    【解决方案5】:

    你可以使用 Array.prototype.some

    posts.filter(
      (elem) => (
        elem.category_array.some(
          elem => elem.slug === currentCategory;
        )
      )
    )
    

    【讨论】:

      猜你喜欢
      • 2018-11-06
      • 1970-01-01
      • 1970-01-01
      • 2021-04-14
      • 2022-12-07
      • 2020-10-17
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多