我的数据类似于以下内容:
学生名单和他们就读的学校
[
{
"uid": 100,
"name": "Adam",
"school": {
"id": 1,
"name": "NYHS"
}
},
{
"uid": 101,
"name": "Bob",
"school": {
"id": 2,
"name": "PAHS"
}
},
{
"uid": 102,
"name": "Charles",
"school": {
"id": 1,
"name": "NYHS"
}
},
{
"uid": 103,
"name": "David",
"school": {
"id": 3,
"name": "MMDS"
}
}
]
我希望将其转化为学校名单,让学生参加。
[
{
"id": 1,
"name": "NYHS",
"students": [
{
"uid": 100,
"name": "Adam"
},
{
"uid": 102,
"name": "Charles"
},
]
},
"id": 2,
"name": "NYHS",
"students": [
{
"uid": 101,
"name": "Bob"
}
]
},
"id": 3,
"name": "MMDS",
"students": [
{
"uid": 103,
"name": "David"
}
]
},
]
我有一个工作版本,但它很长,可能没有高效。有更短/更快的方法吗?
真的不管用什么语言。
尝试使用map / reduce,我得到了独特的学校,但不确定如何将学生合并到其中。
$schools = array_reduce(
array_map(function ($a) {
return $a['school'];
}, $students),
function ($s, $i) {
if (count(array_filter($s, function ($j) use ($i) {
return $j['id'] == $i['id'];
})) == 0) {
array_push($s, $i);
}
return $s;
},
array()
);
答案 0 :(得分:2)
我可能通过调用.reduce()
来创建一个具有每个学校属性的对象,然后将该对象映射到最终输出数组来最小化循环:
var input = [ // whitespace compressed to avoid vertical scrolling
{ "uid": 100, "name": "Adam", "school": { "id": 1, "name": "NYHS" } },
{ "uid": 101, "name": "Bob", "school": { "id": 2, "name": "PAHS" } },
{ "uid": 102, "name": "Charles", "school": { "id": 1, "name": "NYHS" } },
{ "uid": 103, "name": "David", "school": { "id": 3, "name": "MMDS" } }
]
var schoolObj = input.reduce(function(p,c) {
if (!(c.school.id in p))
p[c.school.id] = { id: c.school.id, name: c.school.name, students: [] }
p[c.school.id].students.push({ uid: c.uid, name: c.name })
return p
}, {})
var schoolArr = Object.keys(schoolObj).map(function(s) { return schoolObj[s] })
console.log(schoolArr)
答案 1 :(得分:1)
以下是一种方法:
function myTransform(input) {
// Store the output of the transform as an object
// Here I assume that the school id is unique
var output = {};
input.forEach((e) => {
if (!output[e.school.id]) {
// If the school id doesn't exist in the output then generate it, and put the school & student data into it
output[e.school.id] = {
id: e.school.id,
name: e.school.name,
students: [{
uid: e.uid,
name: e.name
}]
};
} else {
// If the school id exists in the output, then push the student data into it
output[e.school.id].students.push({
uid: e.uid,
name: e.name
});
}
});
// Convert the output into an array
return Object.keys(output).map((e) => output[e]);
}
我使用了一个对象来存储输出,以避免使用嵌套循环(我不确定这是否是最好的方法)。最后,我将对象转换为数组。
答案 2 :(得分:1)
var arr = [{"uid":100,"name":"Adam","school":{"id":1,"name":"NYHS"}},{"uid":101,"name":"Bob","school":{"id":2,"name":"PAHS"}},{"uid":102,"name":"Charles","school":{"id":1,"name":"NYHS"}},{"uid":103,"name":"David","school":{"id":3,"name":"MMDS"}}];
var result = Object.values( // get the values of the hash object
arr.reduce(function(hash, o) {
var id = o.school.id; // get the school id
hash[id] = hash[id] || {id: id, name: o.school.name, students: []}; // check if the school is already in the hash object, if not create add it
hash[id].students.push({id: o.id, name: o.name}); // add this student to its students array
return hash;
}, {})
);
console.log(result);

答案 3 :(得分:1)
这是一个PHP版本,它保留了您可能拥有的所有其他字段。
$output = array_reduce($input, function($result, $item) {
$id = $item["school"]["id"];
if (!isset($result[$id])) {
$result[$id] = array_merge($item["school"], ["students" => []]);
}
$result[$id]["students"][] = array_diff_key($item, ["school" => null]);
return $result;
}, []);