过滤具有嵌套结构的JavaScript对象

时间:2019-09-09 19:45:09

标签: javascript

let data = [
    {
        title: 'aa',
        releases: [
            { version: '1', owner: 'john'},
            { version: '2', owner: 'bob'}
        ]
    },
    {
        title: 'bb',
        releases: [
            { version: '1', owner: 'john'},
            { version: '2', owner: 'jack'}
        ]
    },
    {
        title: 'cc',
        releases: [
            { version: '1', owner: 'doo'},
            { version: '2', owner: 'park'}
        ]
    },
]

我有一系列类似于上面的对象。

我试图通过owner数组内的releases过滤对象。

我尝试过的是

data.filter(item => 
        ['john'].some(
            item.releases.some(
                obj=>obj.owner.toLowerCase().includes(['john'])
            )
        )
    )

以后我使用了一个字符串数组来进行多个搜索查询。但这给我一个错误

Uncaught TypeError: true is not a function

我该如何解决?

结果应该是所有john数组中拥有releases作为所有者的所有对象

4 个答案:

答案 0 :(得分:2)

那个['john'].some(的电话并没有帮助。你已经有了没有这个的逻辑。

由于将some()(返回布尔值)的结果传递给some()(期望有一个函数),所以出现了该错误。

此外,在询问字符串是否包含字符串时,您应该传递字符串,而不是数组。

const filteredData = data.filter(item => 
    item.releases.some(
        obj => obj.owner.toLowerCase().includes('john')
    )
)

答案 1 :(得分:0)

有些人希望函数不是值,最外层的是您只是传递需要传递函数的值

data.filter(item =>  
        ['john'].some( () =>      //  <--- function
            item.releases.some(
                obj=>obj.owner.toLowerCase().includes('john')
            )
        )
    )

事实上,您不需要外部

data.filter(item =>  
     item.releases.some(
       obj=>obj.owner.toLowerCase().includes('john')
    )
)

答案 2 :(得分:0)

您可以尝试以下方法:

let data = [
    {
        title: 'aa',
        releases: [
            { version: '1', owner: 'john'},
            { version: '2', owner: 'bob'}
        ]
    },
    {
        title: 'bb',
        releases: [
            { version: '1', owner: 'john'},
            { version: '2', owner: 'jack'}
        ]
    },
    {
        title: 'cc',
        releases: [
            { version: '1', owner: 'doo'},
            { version: '2', owner: 'park'}
        ]
    },
];

var result = data.filter(x => x.releases.some(rls => rls.owner.toLowerCase().includes(['john'])));

console.log(result);

答案 3 :(得分:0)

如果要检查单个名称,则可以取消此答案。但是,如果问题的目的是检查多个名称,则可以通过以下方式修复代码。

问题是您要为第一个true调用提供一个false / some值,这应该是一个函数。

const names = ['john'];
data.filter(item =>
  names.some(name => // added `name =>`
    item.releases.some(release =>
      release.owner.toLowerCase().includes(name) // changed `['john']` into `name`
    )
  )
);

但是,您也可以使用正则表达式以更少的迭代次数实现相同的功能。

// https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Regular_Expressions#Escaping
const escapeRegExp = string => string.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');

const names = ['john'],
      pattern = names.map(escapeRegExp).join("|"),
      regex = new RegExp(pattern, "i"); // i = ignore case (removing the need of toLowerCase)

data.filter(item => item.releases.some(release => release.owner.match(regex)));