将嵌套的数组合并为一个数组?

6
假设我有一个对象数组,看起来类似于这样:
[
   {
     id: ...,
     name: "...",
     users: [1, 2, 3]
    },
    ...
]

有没有一种方法可以轻松地将每个对象的.users数组合并成一个数组?
7个回答

9
拔取 'n' 展平将会满足你的需求:
var result = _.flatten(_.pluck(data, 'users'));

编辑

正如Richard所指出的,在lodash 4.0.0版本中删除了pluck函数,但在撰写本文时的最新版本的underscore(1.8.3)中仍然存在。

使用map函数替换pluck可以同时适用于lodash和underscore:

var result = _.flatten(_.map(data, 'users'));

这是最简单的解决方案。 - m0ngr31
2
现在这段代码是 var result = .flatten(.map(data, 'users')); 因为pluck已经被弃用并移除了。 - Richard Lindhout
1
感谢@RichardLindhout!已编辑答案以反映更改。 - Gruff Bunny
当然,使用_.union(...)来仅包含所有唯一的ID。 - Ted

2
不了解 lodash 或 underscore,但可以使用 Array 的原生 forEachconcat 方法(underscore 可能有等效的方法,并且对于旧浏览器也有 polyfill)。
var data = [{
     id: ...,
     name: "...",
     users: [1, 2, 3]
    },
    ...
];
var allUsers = [];
data.forEach(function(obj){
   allUsers = allUsers.concat(obj.users);
});

console.log(allUsers);

演示

var data = [{
     id: 1,
     name: "...",
     users: [1, 2, 3]
    },
    {
     id: 2,
     name: "....",
     users: [4, 5, 6]
    },
    {
     id: 3,
     name: "...",
     users: [7, 8, 9]
    },            
];
var allUsers = [];
data.forEach(function(obj){
   allUsers = allUsers.concat(obj.users);
});

document.querySelector("#log").innerHTML = allUsers.join(",");
<div id="log"></div>


2

使用lodash:

var objects = [
   {
     id: "...",
     name: "...",
     users: [1, 2, 3]
    },
   {
     id: "...",
     name: "...",
     users: [4, 5, 6]
    },
    //...
];
var allUsers = _.flatMap(objects, function(o){return o.users;});

console.log(allUsers);
// allUsers: [1,2,3,4,5,6]
<script src="https://cdn.jsdelivr.net/lodash/4.17.4/lodash.min.js"></script>


这就是我一直在寻找的。谢谢! - m0ngr31

1
这将循环遍历原始数组并返回一个仅包含users数组值的新数组。我使用Array.prototype.reduce来保持一切都被包含,但你也可以用for循环实现。
var data = [{id: 1, name: "A", users: [1, 2, 3]},
            {id: 2, name: "B", users: [4, 5, 6]},
            {id: 3, name: "C", users: [7, 8, 9]}];
var allUsers = data.reduce(function (result, current) {
    Array.prototype.push.apply(result, current.users);
    return result;
}, []);

我使用 Array.prototype.push 的原因是修改现有的数组,而不是通过使用类似 Array.prototype.concat 的方法来创建多个副本。

0
你可以使用 Array.prototype.push 方法:
var res = [];
for (var i = 0; i < o.length; i++) {
   res.push.apply(res, o[i].users);
}

如果数组应该包含唯一元素:

res = res.filter(function(val, i, arr) { 
    return arr.indexOf(val) === i;
});

1
res.push(o[i].users); - Ryan
2
@self 这将创建一个数组的数组。 - Ram
这会导致重复的用户。 - BatScream
"a.push.apply(a, b)" 就像 "a = a.concat(b)" 一样。 - elclanrs
刚刚测试过了,你是对的。不过有点奇怪。这似乎像是一个黑客攻击。 - Ryan
@self 上面的代码片段使用了 Function.prototype.apply 方法。apply 的工作方式可能会让人感到困惑,但它并不是一种 hackish 的方法。 - Ram

0
var a = [
   {
     id: 1,
     name: "...",
     users: [1, 2, 3]
    },
    ...
];
var res = new Array();
for(var i = 0; i < a.length; i++) {
    a[i].users.forEach(function(val) { res.push(val); }
);

-1

这可能不是最有效的方法,但它可以实现你想要的功能。

在这里查看fiddle:http://jsfiddle.net/TylersDesk/3x1w8y95/

var objects = [
    {
        time: 1234,
        users: ["Joe", "Bob", "Blake"]
    },
    {
        time: 1234,
        users: ["Annie", "Gale"]
    }
]

var allUsers = []

for (i=0; i<objects.length; i++) {
    for (key in objects[i]) {
        if (key === "users") {
            console.log('found users');
            console.log(objects[i][key]);

            for (g=0; g<objects[i][key].length; g++) {
                console.log(objects[i][key][g]);

                //Add to array
                allUsers.push(objects[i][key][g]);          
            }
        }
    }
}

//Output all users
console.log(allUsers);

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接