对象数组:为每个指定键创建一个具有值的新对象

3

我有一个对象数组,从CSV文件中提取,如下所示:

    const data = [
  { name: 'p1', 'date started': 'April 2007', Houston: '375', Dallas: '508', Austin: '', 'El Paso': '1232' },
  { name: 'p2', 'date started': 'April 2017', Houston: '', Dallas: '', Austin: '', 'El Paso': '43' },
  { name: 'p3', 'date started': 'June 2012', Houston: '18789', Dallas: '', Austin: '8977', 'El Paso': '6754656' },
  { name: 'p4', 'date started': 'December 2015', Houston: '878', Dallas: '4556', Austin: '987', 'El Paso': '1456232' }
]

我正在创建一些数据的图表和表格,需要创建两个新键“location”和“value”,并为每个对象中的每个位置值创建新对象,如下所示:

    const newData = [
  { location: 'Houston', value: '375', name: 'p1', 'date started': 'April 2007' },
  { location: 'Dallas', value: '508', name: 'p1', 'date started': 'April 2007' },
  { location: 'El Paso', value: '1232', name: 'p1', 'date started': 'April 2007' },
  { location: 'El Paso', value: '43', name: 'p2', 'date started': 'April 2017' },
  { location: 'Houston', value: '18789', name: 'p3', 'date started': 'June 2012' },
  { location: 'Austin', value: '8977', name: 'p3', 'date started': 'June 2012' },
  { location: 'El Paso', value: '6754656', name: 'p3', 'date started': 'June 2012' },
  { location: 'Houston', value: '878', name: 'p4', 'date started': 'December 2015' },
  { location: 'Dallas', value: '4556', name: 'p4', 'date started': 'December 2015' },
  { location: 'Austin', value: '987', name: 'p4', 'date started': 'December 2015' },
  { location: 'El Paso', value: '1456232', name: 'p4', 'date started': 'December 2015' }
]

之前我在一个类似的项目中也需要这样做,当时时间很紧,最终只能手动编辑原始CSV文件。我不想再那样做了。到目前为止,我已经尝试了各种map/forEach和Object.keys的组合,但都没有成功。

如果您有任何想法,将不胜感激!

4个回答

2
你可以遍历对象的所有键,并排除不需要的属性,为结果集构建新的对象。

var data = [{ name: 'p1', 'date started': 'April 2007', Houston: '375', Dallas: '508', Austin: '', 'El Paso': '1232' }, { name: 'p2', 'date started': 'April 2017', Houston: '', Dallas: '', Austin: '', 'El Paso': '43' }, { name: 'p3', 'date started': 'June 2012', Houston: '18789', Dallas: '', Austin: '8977', 'El Paso': '6754656' }, { name: 'p4', 'date started': 'December 2015', Houston: '878', Dallas: '4556', Austin: '987', 'El Paso': '1456232' }],
    result = data.reduce(function (r, o) {
        Object.keys(o).forEach(function (k)  {
            if (['name', 'date started'].includes(k) || !o[k]) {
                return;
            }
            r.push({ location: k, value: o[k], name: o.name, 'date started': o['date started'] });
        });
        return r;
    }, []);

console.log(result);
.as-console-wrapper { max-height: 100% !important; top: 0; }


这太聪明了,运行良好,将为我节省大量时间!非常感谢! - Joshua Swiss
1
@JoshuaSwiss:在现实生活中,不要使用逻辑运算符来代替流程控制。需要阅读您的代码的人会对此提出严重反对意见。更明智的解决方案将如下所示:https://jsfiddle.net/5fvLc8mm/ 它使用适当的流程控制,避免了排除键数组的重复分配,并在 o[k] 为真值时避免了从该数组进行查找。当代码布局合理时,这些问题更容易被发现。 - llama

1
你可以通过遍历所有的旧对象 items ,然后遍历旧对象中的所有键,基于此构建一个新数组,如下所示。

const data = [
        { name: 'p1', 'date started': 'April 2007', Houston: '375', Dallas: '508', Austin: '', 'El Paso': '1232' },
        { name: 'p2', 'date started': 'April 2017', Houston: '', Dallas: '', Austin: '', 'El Paso': '43' },
        { name: 'p3', 'date started': 'June 2012', Houston: '18789', Dallas: '', Austin: '8977', 'El Paso': '6754656' },
        { name: 'p4', 'date started': 'December 2015', Houston: '878', Dallas: '4556', Austin: '987', 'El Paso': '1456232' }
    ];

function transform() {
    
    var newObjects = [];
    data.forEach(item => {
        Object.keys(item).forEach(keyName => {
            if (keyName !== "name" && keyName !== "date started") {
                newObjects.push({
                    location: keyName,
                    value: item[keyName],
                    ["date started"]: item["date started"],
                    name: item["name"]
                })
            }
        });
    });
    return newObjects;
}

console.log(transform(data));

希望这有所帮助。

1
这变得相当简洁,使用解构赋值和剩余/展开语法。

const data = [
  { name: 'p1', 'date started': 'April 2007', Houston: '375', Dallas: '508', Austin: '', 'El Paso': '1232' },
  { name: 'p2', 'date started': 'April 2017', Houston: '', Dallas: '', Austin: '', 'El Paso': '43' },
  { name: 'p3', 'date started': 'June 2012', Houston: '18789', Dallas: '', Austin: '8977', 'El Paso': '6754656' },
  { name: 'p4', 'date started': 'December 2015', Houston: '878', Dallas: '4556', Austin: '987', 'El Paso': '1456232' }
];

const result = data.reduce((res, obj) => {
  const date_started = obj["date started"];
  delete obj["date started"];
  const {name, ...rest} = obj;
  
  return [...res, ...Object.entries(rest).map(([k,v]) =>
    ({location:k, value:v, name:name, 'date started':date_started})
  )]
}, []);

console.log(result);


如果您希望避免在对象字面量中使用剩余参数,并且不想要空位置,您可以创建一个Set,用于排除非位置键,并使用真值评估来排除不需要的位置。

var data = [{ name: 'p1', 'date started': 'April 2007', Houston: '375', Dallas: '508', Austin: '', 'El Paso': '1232' }, { name: 'p2', 'date started': 'April 2017', Houston: '', Dallas: '', Austin: '', 'El Paso': '43' }, { name: 'p3', 'date started': 'June 2012', Houston: '18789', Dallas: '', Austin: '8977', 'El Paso': '6754656' }, { name: 'p4', 'date started': 'December 2015', Houston: '878', Dallas: '4556', Austin: '987', 'El Paso': '1456232' }];

var exc = new Set(['name', 'date started']);
var result = data.reduce((r, o) =>
    [
      ...r, 
      ...Object.entries(o)
        .filter(([k, v]) => v && !exc.has(k))
        .map(([k, v]) => ({ location: k, value: v, name: o.name, 'date started': o['date started'] }))
    ]
, []);

console.log(result, null, 2);


对象休息。 - Nina Scholz
@NinaScholz:只有那些尚未实现该功能的浏览器才会失败。您是否不知道这个功能? - llama
@NinaScholz 去哪了? - llama
我知道这个功能,但它并不总是被实现了。 - Nina Scholz
@NinaScholz:没有功能是永远实现的。这就是为什么我们需要转译器的原因。 - llama

1

通过完全通用的方法,OP可以控制所有必须“按原样”分配给每个新创建的数据项的键值对...甚至是每个数据条目元组的代理键。

var data = [
  { name: 'p1', 'date started': 'April 2007', Houston: '375', Dallas: '508', Austin: '', 'El Paso': '1232' },
  { name: 'p2', 'date started': 'April 2017', Houston: '', Dallas: '', Austin: '', 'El Paso': '43' },
  { name: 'p3', 'date started': 'June 2012', Houston: '18789', Dallas: '', Austin: '8977', 'El Paso': '6754656' },
  { name: 'p4', 'date started': 'December 2015', Houston: '878', Dallas: '4556', Austin: '987', 'El Paso': '1456232' }
];

var newData = data.reduce(function (collector, dataItem) {
  var
  //itemEntryList = Object.entries(dataItem); // if available, otherwise next line ...
    itemEntryList = Object.keys(dataItem).map(function (key) {
      return [key, dataItem[key]];
    }),
    assignerList = [],
    assignerKey,
    idx = -1,
    keyForDataKey = collector.keyForDataKey,
    keyForDataValue = collector.keyForDataValue,
    protectedKeyList = collector.protectedKeyList;

  // implement a local `reject` ... for all key value pairs that have to be copied "as is".
  while ((assignerKey = itemEntryList[++idx]) && (assignerKey = assignerKey[0])) {
    if (protectedKeyList.some(function (protectedKey) {
      return (assignerKey === protectedKey);
    })) {
      assignerList.push({ key: assignerKey, value: itemEntryList[idx][1] });
      itemEntryList.splice(idx, 1);
      --idx;
    }
  }
  // create new data-item base-structures from the remaining `dataItem` tuples after the `reject` step.
  var dataItemList = itemEntryList.reduce(function (itemList, dataTuple) {

    var tupleValue = dataTuple[1];
    if (tupleValue) {
      var newDataItem = {};
      newDataItem[keyForDataKey] = dataTuple[0];
      newDataItem[keyForDataValue] = tupleValue;

      itemList.push(newDataItem);
    //itemList.push({ location: dataTuple[0], value: tupleValue });
    }
    return itemList;

  }, []);

  // for each new data item ...
  dataItemList.map(function (newDataItem) {
    return assignerList.reduce(function (dataItem, assignerItem) {

      // ... reassign all formerly rejected key value pairs that have to be copied "as is".
      dataItem[assignerItem.key] = assignerItem.value;
      return dataItem;

    }, newDataItem)
  });

  // collect all new data items.
  collector.dataItemList = collector.dataItemList.concat(dataItemList);

  return collector;

}, {

  keyForDataKey:    'location',
  keyForDataValue:  'value',

  protectedKeyList: ['name', 'date started'],
  dataItemList:     []

}).dataItemList;


console.log('data : ', data);
console.log('newData : ', newData);
.as-console-wrapper { max-height: 100%!important; top: 0; }


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接