如何使用 lodash/underscorejs 拆分具有特定条件的对象的 javascript 数组
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/30645214/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
How to split javascript array of object with specific condition using lodash/underscorejs
提问by waskito
I have array of objects like this:
我有这样的对象数组:
var data = [
{
type : "parent",
name : "A"
},
{
type : "child",
name : "1"
},
{
type : "child",
name : "2"
},
{
type : "parent",
name : "B"
},
{
type : "child",
name : "3"
}
]
and I want to move child objects into parent objects, splitted by the parrent object (there is no given key from child object is belonged to which parrent). So it's only separate by the parent object. To be simple I want to change the array into :
并且我想将子对象移动到父对象中,由父对象拆分(没有来自子对象的给定键属于哪个父对象)。所以它只被父对象分开。为简单起见,我想将数组更改为:
[
{
type : "parent",
name : "A",
child: [
{
type : "child",
name : "1"
},
{
type : "child",
name : "2"
}
]
},
{
type : "parent",
name : "B",
child: [
{
type : "child",
name : "3"
}
]
}
]
I have read lodash about chunkbut it's no use.
我已经阅读了关于chunk 的lodash但它没有用。
回答by Jason Cust
You can use either the native Array.prototype.reduce
function or lodash's reduce
:
您可以使用本机Array.prototype.reduce
函数或 lodash 的reduce
:
var data = [{
type: "parent",
name: "A"
},
{
type: "child",
name: "1"
},
{
type: "child",
name: "2"
},
{
type: "parent",
name: "B"
},
{
type: "child",
name: "3"
}
];
// If using _.reduce then use:
// var newData = _.reduce(data, function(arr, el) {...}, []);
var newData = data.reduce(function(arr, el) {
if (el.type === 'parent') {
// If el is pushed directly it would be a reference
// from the original data object
arr.push({
type: el.type,
name: el.name,
child: []
});
} else {
arr[arr.length - 1].child.push({
type: el.type,
name: el.name
});
}
return arr;
}, []);
console.log(newData);
UPDATE: Small changes using newer ES language features
更新:使用较新的 ES 语言功能的小改动
const data = [{
type: "parent",
name: "A"
},
{
type: "child",
name: "1"
},
{
type: "child",
name: "2"
},
{
type: "parent",
name: "B"
},
{
type: "child",
name: "3"
}
];
const newData = data.reduce((arr, el) => {
if (el.type === 'parent') {
// If el is pushed directly it would be a reference
// from the original data object
arr.push({...el, child: []});
} else {
arr[arr.length - 1].child.push({...el});
}
return arr;
}, []);
console.log(newData);
回答by Brandon Horst
Here's a lodash solution that may be a bit easier to understand. CodePen
这是一个 lodash 解决方案,可能更容易理解。代码笔
A few notes:
一些注意事项:
- this modifies the incoming data object - if that's a problem we can toss in some
_.clone()
calls. - This will only work if each parent has 26 or fewer children, because of the
name: "ab"
pattern you picked
- 这会修改传入的数据对象 - 如果这是一个问题,我们可以在某些
_.clone()
调用中进行折腾。 - 由于
name: "ab"
您选择的模式,这仅适用于每个父母有 26 个或更少孩子的情况
var lastParent;
var result = _.chain(data)
.groupBy(function (item) {
if (item.type === 'parent') lastParent = item.name
return lastParent
})
.map(function (group) {
var parent = _.first(group)
parent.child = _.chain(group)
.slice(1)
.map(function (child, index) {
child.name = parent.name.toLowerCase() + String.fromCharCode(index + 97)
return child
})
.value()
return parent
})
.value()
console.log(result)
回答by Alex Tartan
Plain javascript version:
纯javascript版本:
var newArr = [];
var j=0;
var k=0;
for (var i = 0; i <data.length; i++) {
if(data[i].type == 'parent'){
newArr[j] = data[i];
newArr[j].children = [];
j++;
k=0;
}
else {
data[i].name = newArr[j-1].name.toLowerCase() + String.fromCharCode(k + 97)
newArr[j-1].children[k] =data[i];
k++;
}
}
console.log(newArr)
I am assuming here that the parent is alwaysplaced before the children, as provided in your example data.
我在这里假设父级总是放在子级之前,如示例数据中提供的那样。
Also, it would be good if you can prevent parents with 26+ children. This would cause String.fromCharCode(k + 97)
to print strange characters. For this, see http://www.asciitable.com/
另外,如果你能阻止有 26 岁以上孩子的父母,那就太好了。这会导致String.fromCharCode(k + 97)
打印奇怪的字符。为此,请参见http://www.asciitable.com/
回答by ZhiLI
for (ele in data)
{
if (!data[ele].hasOwnProperty('child') && data[ele].type=='parent')
{
data[ele].child = [];
while(data[parseInt(ele) + 1] && data[parseInt(ele) + 1].type == 'child')
{
data[ele].child.push({type: data[parseInt(ele) + 1].type, name:data[parseInt(ele) + 1].name});
data.splice(parseInt(ele) + 1, 1);
}
}
}
console.log(data);
回答by Walter Chapilliquen - wZVanG
Try simple loop:
尝试简单的循环:
var current, parent, result = [], i = 0;
while(current = data[i++]){
if(current.type === "parent"){
current.child = [];
result.push(current);
parent = current
}else{
current.name = (parent.name + String.fromCharCode(parent.child.length + 97)).toLowerCase();
parent.child.push(current)
}
}