将对象中的键值提取到具有特定字段的对象数组中

Extracting key value from object into array of objects with specific fields

所以我有这个数据:

fields = ['a', 'b', 'c']
data = [{r: 1, a: 2, b: 3, c: 4, h: 5}, {r: 4, a: 9, b: 1, c: 4, h: 5} ... ]

并且我希望能够(首选 lodash)能够做到这一点:

newData = [{r:1, h:5, values: [{name: 'a', value: 2},{name: 'b', value: 3}, {name: 'c', value: 4}], .....]

意味着只从数组中的每个对象中取出 'fields' 对象的字段(它们始终存在)并放入 'values' 属性 中此处显示的格式。

很想听听实现这一目标的最简洁方法的建议!

我这样做了:

function something(data, fields) {

  const formattedData = _.map(data, (currData) => {

    const otherFields = _.omit(currData, fields)

    return { 
      ...otherFields, 
      values: _.flow( 
        currData => _.pick(currData, fields), 
        pickedFields => _.toPairs(pickedFields), 
        pairs => _.map(pairs, pair => { 
          return { name: pair[0], value: pair[1] } 
        })
      )(currData)
    }
  })

  return formattedData
}

哪个可行,但我想知道它是否有点复杂。

您可以map遍历数据中的对象,然后检查键是否在字段数组中:

fields = ["a", "b", "c"];
data = [
  { r: 1, a: 2, b: 3, c: 4, h: 5 },
  { r: 4, a: 9, b: 1, c: 4, h: 5 },
];

let newData = data.map((o) => {
  let newObject = {};
  newObject.values = [];
  for (let k in o) {
    if (fields.includes(k)) {
      newObject.values.push({
        name: k,
        value: o[k]
      });
    } else {
      newObject[k] = o[k];
    }
  }
  return newObject;
});

console.log(newData);

您可以解构对象,选择所需的属性,然后 return 对象的其余部分具有所需的值。

const
    fields = ['a', 'b', 'c'],
    data = [{ r: 1, a: 2, b: 3, c: 4, h: 5 }, { r: 4, a: 9, b: 1, c: 4, h: 5 }],
    result = data.map(o => {
        const values = fields.map(name => {
            let value;
            ({ [name]: value, ...o } = o);
            return { name, value };
        });
        return { ...o, values };
    });

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

_.flow() 方法创建一个函数,您可以提取和命名该函数。此外,流程中的第一个函数接受超过 1 个参数,因此您无需显式传递它。由于 _.toPairs() 是一元的,因此您不需要将其包装在箭头函数中。 对象创建有点烦人。我用过_.zipObject(),但还是很麻烦。

现在您可以在主函数中使用 _.flow() 创建的函数,它的可读性很好:

const { flow, pick, toPairs, map, partial, zipObject, omit } = _

const propsToObjs = flow(
  pick,
  toPairs,
  pairs => map(pairs, partial(zipObject, ['name', 'value'])),
)

const fn = (data, fields) =>
  map(data, currData => ({
    ...omit(currData, fields), 
    values: propsToObjs(currData, fields)
  }))
  
const fields = ['a', 'b', 'c']
const data = [{r: 1, a: 2, b: 3, c: 4, h: 5}, {r: 4, a: 9, b: 1, c: 4, h: 5}]

const result = fn(data, fields)

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

使用 lodash/fp,我们可以使流函数更好,因为 lodash/fp 函数是自动柯里化和迭代优先数据最后(不是参数的相反顺序):

const { flow, pick, toPairs, map, partial, zipObject, omit } = _

const propsToObjs = flow(
  pick,
  toPairs,
  map(zipObject(['name', 'value']))
)

const fn = fields => map(currData => ({
  ...omit(fields, currData), 
  values: propsToObjs(fields, currData)
}))
  
const fields = ['a', 'b', 'c']
const data = [{r: 1, a: 2, b: 3, c: 4, h: 5}, {r: 4, a: 9, b: 1, c: 4, h: 5}]

const result = fn(fields)(data)

console.log(result)
<script src='https://cdn.jsdelivr.net/g/lodash@4(lodash.min.js+lodash.fp.min.js)'></script>