【问题标题】:Reduce array of objects to a single object and call a function for each individual object将对象数组减少为单个对象并为每个单独的对象调用一个函数
【发布时间】:2019-09-30 13:28:37
【问题描述】:

我有一个对象数组。 我需要将其转换为对象的对象。在尝试这样做时,我需要为每个对象调用另一个函数。

你能帮我解决这个问题吗?

代码:

function convertData() {
 var arr = {"items": [ {"type": "color"}, {"type": "number" }]};
 arr.items.reduce(function(item, index) {
   return {
    /*for each obj in items call formatItems before assigning it here */
    item: formatItems(item)
   }
 });

  console.log(arr);
}

function formatItems(item, index) {
  return {
    type: "string",
    id: "item-"+index
  }
}
<button onclick="convertData()">Click me!</button>

预期输出:

{
  "0": {
    "type": "string",
    "id": "item-1"
  },
  "1": {
    "type": "string",
    "id": "item-2"
  }
}

【问题讨论】:

  • 预期输出错误。您在寻找对象数组吗?
  • 您的预期输出无效,它使用对象表示法,但没有属性名称(在外部对象中)。真正想要的输出是什么?
  • "我需要将其转换为对象的对象" 那会是对象的数组吗?还是一个包含属性并且每个都是对象的对象?如果是后者,那么它们的键应该是什么?
  • 关于您的编辑:这仍然无效。您有一个键与与之关联的对象,但第二个键不正确。这些应该在一个数组中还是你期望两个键?
  • 顺便说一句,使用带有序列号的动态id 属性可能是代码异味。最好知道为什么你需要这个。

标签: javascript arrays object iterator reduce


【解决方案1】:

使用属性名称为"0""1" 的对象确实值得怀疑。我只是继续使用一个数组,您可以通过map 轻松创建它(但请继续阅读非数组对象选项):

var result = arr.items.map(formatItems);

现场示例:

function convertData() {
  var arr = {"items": [ {"type": "color"}, {"type": "number" }]};
  var result = arr.items.map(formatItems);
  console.log(result);
}

function formatItems(item, index) {
  return {
    type: "string",
    id: "item-"+index
  };
}

convertData();

但是如果你真的想要一个非数组对象,你的代码是相当接近的,如果你真的想使用reduce;见 cmets:

var result = arr.items.reduce(function(obj, item, index) {
  //                                   ^^^-- receive the "accumulator" as the first param
  obj[index] = formatItems(item); // Create the property on the object
  return obj;                     // Return the same object
}, {});                           // Start with a blank object

现场示例:

function convertData() {
  var arr = {"items": [ {"type": "color"}, {"type": "number" }]};
  var result = arr.items.reduce(function(obj, item, index) {
    //                                   ^^^-- receive the "accumulator" as the first param
    obj[index] = formatItems(item); // Create the property on the object
    return obj;                     // Return the same object
  }, {});                           // Start with a blank object
  console.log(result);
}

function formatItems(item, index) {
  return {
    type: "string",
    id: "item-"+index
  };
}

convertData();

但是,当您只是从回调中传递与接收相同的对象时,reduce 并不是最好的工具。您只需要一个简单的循环:

var result = {};
for (const [index, item] of arr.items.entries()) {
  result[index] = formatItems(item);
}

现场示例:

function convertData() {
  var arr = {"items": [ {"type": "color"}, {"type": "number" }]};
  var result = {};
  for (const [index, item] of arr.items.entries()) {
    result[index] = formatItems(item);
  }
  console.log(result);
}

function formatItems(item, index) {
  return {
    type: "string",
    id: "item-"+index
  };
}

convertData();

Adiga has a much simpler ES2015+ option,不过。


或者如果您需要 ES2015 之前的版本:

var result = {};
for (int index = 0; index < arr.items.length; ++index) {
  result[index] = formatItems(arr.items[index]);
}

现场示例:

function convertData() {
  var arr = {"items": [ {"type": "color"}, {"type": "number" }]};
  var result = {};
  for (var index = 0; index < arr.items.length; ++index) {
    result[index] = formatItems(arr.items[index]);
  }
  console.log(result);
}

function formatItems(item, index) {
  return {
    type: "string",
    id: "item-"+index
  };
}

convertData();

【讨论】:

    【解决方案2】:

    在 ES6 中,您可以 map arr.itemsspread{} 中生成结果数组。这将创建一个以数组索引作为属性的对象

    function formatItems(item, index) {
      return { type: "string", id: "item-"+index }
    }
    
    const arr = { "items": [ {"type": "color"}, {"type": "number" }] };
    
    const output = { ...arr.items.map(formatItems) } 
          
    console.log(output)

    【讨论】:

    • 使用 OP 的formatItems,简直就是let output = {...arr.items.map(formatItems)}; 不错!
    • 我猜 OP 需要一个 ES5 解决方案。你的 ES2015+ 比我的要好得多。 :-) 不敢相信我没想到。
    • @T.J.Crowder 谢谢,我更新了你提到的答案,因为formatItems 的内容是dummy according to OP
    • 它稍微改进了一下,但它已经是一个非常好的答案。 :-)
    【解决方案3】:

    您需要将initialValue 作为空object 传递给reducer。

    示例:

    function convertData() {
     var arr = {"items": [ {"type": "color"}, {"type": "number" }]};
     const res = arr.items.reduce(function(acc, item, index) {
        const out = formatItems(item, index)
    
        //change this if you need an indexed keys, like acc[index] = out
        acc[out.id] = out
        return acc
     }, {});
    
       console.log(res);
    }
    
    function formatItems(item, index) {
      return {
        type: "string",
        id: "item-"+index
      }
    }
    convertData()
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2018-01-05
      • 1970-01-01
      • 2016-09-23
      • 2022-11-08
      • 2022-01-22
      • 2018-07-10
      • 2021-09-16
      相关资源
      最近更新 更多