Lodash keyBy用于多个嵌套级别数组

时间:2016-12-02 17:36:00

标签: javascript arrays object lodash

我有一个对象数组,我希望将其转换为键值对的映射,并以id为键。但是,我想在根级别和recipes属性中执行此操作。

数组resp

[
  {
    "id": "1",
    "recipes": [
      {
        "id": 4036
      },
      {
        "id": 4041
      }
    ]
  },
  {
    "id": "2",
    "recipes": [
      {
        "id": 4052
      },
      {
        "id": 4053
      }
    ]
  }
]

我遇到了_.keyBy(),它将一个属性映射为键,但它不允许嵌套级别。

功能:

var respObj = _.keyBy(resp, 'id');

是否有一个优雅的解决方案来按摩resp以使所有嵌套在数组中的对象都使用id作为关键?

谢谢!

3 个答案:

答案 0 :(得分:3)

这是一个通用的解决方案,在数组上递归运行_.keyBy,以及它们内部的对象:

function deepKeyBy(arr, key) {
  return _(arr)
    .map(function(o) { // map each object in the array
      return _.mapValues(o, function(v) { // map the properties of the object
        return _.isArray(v) ? deepKeyBy(v, key) : v; // if the property value is an array, run deepKeyBy() on it
      });
    })
    .keyBy(key); // index the object by the key
}

我在示例(成分)中添加了另一个级别的数据:

function deepKeyBy(arr, key) {
  return _(arr)
    .map(function(o) {
      return _.mapValues(o, function(v) {
        return _.isArray(v) ? deepKeyBy(v, key) : v;
      });
    })
    .keyBy(key);
}

var arr = [{
  "id": "1",
  "recipes": [{
    "id": 4036,
    "ingerdients": [{
      "id": 5555555
    }, {
      "id": 5555556
    }, {
      "id": 5555557
    }]
  }, {
    "id": 4041
  }]
}, {
  "id": "2",
  "recipes": [{
    "id": 4052
  }, {
    "id": 4053
  }]
}];

var result = deepKeyBy(arr, 'id');

console.log(result);
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.2/lodash.min.js"></script>

答案 1 :(得分:2)

您可以获得扁平的食谱集合,连接响应,然后按ID键入:

var result = _.chain(resp)
    .flatMap('recipes')
    .concat(resp)
    .keyBy('id')
    .value()

flatMap调用将从响应中获取所有配方并压平数组,以便我们留下这个:

[
    { "id": 4036 },
    { "id": 4041 },
    { "id": 4052 },
    { "id": 4053 }
]

然后使用concat将响应附加到此数组,然后我们将:

[
    { "id": 4036 },
    { "id": 4041 },
    { "id": 4052 },
    { "id": 4053 },
    { "id": "1", recipes: ... }, 
    { "id": "2", recipes: ... } 
]

最后,我们使用keyBy来获取所需的结构。

		var resp = [
		  {
		    "id": "1",
		    "recipes": [
		      {
		        "id": 4036
		      },
		      {
		        "id": 4041
		      }
		    ]
		  },
		  {
		    "id": "2",
		    "recipes": [
		      {
		        "id": 4052
		      },
		      {
		        "id": 4053
		      }
		    ]
		  }
		]

	var result = _.chain(resp)
		.flatMap('recipes')
		.concat(resp)
		.keyBy('id')
		.value()

document.getElementById('result').textContent = JSON.stringify(result);
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.15.0/lodash.min.js"></script>

<p>
  <pre id="result"></pre>
</p>

答案 2 :(得分:2)

您可以使用_.keyBy_.mapValues

执行此操作
_.chain(resp)
    .keyBy('id')
    .mapValues(function(item) {
        item.recipes = _.keyBy(item.recipes, 'id');
        return item;
    })
    .value();