Groupby 不使用下划线 js

Groupby without using underscore js

我有一个按 ID 分组的集合。每个 id 包含对象数组。我想遍历它并创建一个目标集合,它将按 "Id" 列分组,如示例所示。我不会使用下划线js。我必须使用 javascript reduce 方法来实现这一点。

var targetCollection = [{
    123456: [
        { "Id": "1", "name": "xxx", "age": "22" },
        { "Id": "1", "name": "yyy", "age": "15" },
        { "Id": "5", "name": "zzz", "age": "59" }
    ],
    789456: [
        { "Id": "1", "name": "xxx", "age": "22" },
        { "Id": "1", "name": "yyy", "age": "15" },
        { "Id": "5", "name": "zzz", "age": "59" }
    ]
}]

var targetOutput = [{
    123456: {
        1: [{ "Id": "1", "name": "xxx", "age": "22" }, { "Id": "1", "name": "yyy", "age": "15" }],
        5: [{ "Id": "5", "name": "zzz", "age": "59" }]
    },
    789456: {
        1: [{ "Id": "1", "name": "xxx", "age": "22" }, { "Id": "1", "name": "yyy", "age": "15" }],
        5: [{ "Id": "5", "name": "zzz", "age": "59" }]
    }
}]

Code Snippet I have tried which didn't work

var newArray = [];
$.each(targetCollection, function (key, value) {
    var newTarget = $(this);
    var targetCollectionNew = newTarget.reduce(function (result, current) {
        result[current.ParentAreaID] = result[current.ParentAreaID] || [];
        result[current.ParentAreaID].push(current);
        return result;
    }, {});

    newArray.push(targetCollectionNew);
});

console.log('newArray', newArray);

我试过数组归约方法,但没有用。请帮我。

你最初尝试的问题是你需要有两个循环,因为在第一个循环中 newValue 是一个对象而不是数组,所以它上面没有 reduce 方法。

更简单的解决方案是在第二个循环中使用 map(您可以使用 forEach$.each)和 reduce(我使用简单的 for-in)。

像这样:

var targetCollection = [{
    123456: [
        { "Id": "1", "name": "xxx", "age": "22" },
        { "Id": "1", "name": "yyy", "age": "15" },
        { "Id": "5", "name": "zzz", "age": "59" }
    ],
    789456: [
        { "Id": "1", "name": "xxx", "age": "22" },
        { "Id": "1", "name": "yyy", "age": "15" },
        { "Id": "5", "name": "zzz", "age": "59" }
    ]
}];

var result = targetCollection.map(function(obj) {
    for (var key in obj) {
        obj[key] = obj[key].reduce(function(prev, curr) {
            if (!prev[curr.Id]) prev[curr.Id] = [];
            prev[curr.Id].push(curr);
            return prev;
        }, {});
    }
    return obj;
});

document.write('<pre>' + JSON.stringify(result, null, 4) + '</pre>');

您应该比较当前对象 targetCollection 和您想要的输出对象 targetOutput,以规划您需要的转换:

targetCollection: Array --> Object --> Array --> Object
targetObject: Array --> Object --> Object --> Array --> Object

你可以看到外层数组将是一个1:1映射,所以这里不需要减少。

下一层是一个对象,但它又是一个 1:1 映射。但是,因为 JavaScript 通过引用传递对象,您将需要创建一个新对象以避免修改原始对象。由于我们是从另一个对象创建一个对象,我们可以利用 Object.keys 的强大功能创建一个数组,然后使用 Array.reduce 从这些键创建一个对象。

第 3 层是我们第一次遇到结构从 Array 到 Object 的真正转换。同样,我们可以使用 Array.reduce 来帮助执行此步骤。

所以从这个攻击计划你可以看到流量应该是map --> reduce --> reduce

var targetCollection = [{
  123456: [{
    "Id": "1",
    "name": "xxx",
    "age": "22"
  }, {
    "Id": "1",
    "name": "yyy",
    "age": "15"
  }, {
    "Id": "5",
    "name": "zzz",
    "age": "59"
  }],
  789456: [{
    "Id": "1",
    "name": "xxx",
    "age": "22"
  }, {
    "Id": "1",
    "name": "yyy",
    "age": "15"
  }, {
    "Id": "5",
    "name": "zzz",
    "age": "59"
  }]
}];

// 1:1 mapping
var targetOutput = targetCollection.map(function(obj) {
  // 1:1 mapping but we need to create a new object to
  //   avoid modifying the original object
  // Object.keys returns an array of keys (that are enumerable)
  //   and then reduce creates the new object
  return Object.keys(obj).reduce(function(newObj, key) {
    // The desired transformation takes place here
    newObj[key] = obj[key].reduce(function(idObj, el) {
      idObj[el.Id] = idObj[el.Id] || [];
      // This will pass by reference the internal objects
      //   so you could use the prior technique to create
      //   a new object to avoid downstream modification
      idObj[el.Id].push(el);

      return idObj;
    }, {});

    return newObj;
  }, {});
});

document.write('<h3>targetCollection</h3><pre>' + JSON.stringify(targetCollection, null, 4) + '</pre>');
document.write('<h3>targetOutput</h3><pre>' + JSON.stringify(targetOutput, null, 4) + '</pre>');