优化阵列反转变换

时间:2017-02-16 05:15:04

标签: javascript php arrays algorithm

我的数据类似于以下内容:

学生名单和他们就读的学校

[
    {
        "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()
);

4 个答案:

答案 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;
}, []);

Try it online