Javascript 或 Ramda 按属性转换 JSON

Javascript or Ramda Transform JSON By Attributes

我在我的项目中使用 Ramda library

是否可以转换以下 JSON 数组

来自

[
   {
     "id": 1,
     "name": "test",
   },
   {
     "id": 2,
     "name": "test2"
   }

];

[
   {
     "id": 1,
     "id": 2,

   },
   {
     "name": "test",
     "name": "test2"
   }

];

求助

对象不能有多个具有相同键的属性,所以 { "id": 1, "id": 2 }{ "name": "test", "name": "test2" } 无效。我假设您需要一个 ID 数组和一个名称数组:

[[1, 2, 3], ['test', 'test2', 'test3']]

如果所有对象都具有相同的键顺序 - 即没有 { id: 1, name: 'test'}{ name: 'test2', id: 1 },并且您需要对象中的所有值,则可以将对象映射到它们的值,并且然后转置:

const { pipe, map, values, transpose } = R;

const fn = pipe(
  map(values),
  transpose,
);

const arr = [{"id":1,"name":"test"},{"id":2,"name":"test2"},{"id":3,"name":"test3"}];

const result = fn(arr);

console.log(result);
<script src="https://cdnjs.cloudflare.com/ajax/libs/ramda/0.27.1/ramda.min.js" integrity="sha512-rZHvUXcc1zWKsxm7rJ8lVQuIr1oOmm7cShlvpV0gWf0RvbcJN6x96al/Rp2L2BI4a4ZkT2/YfVe/8YvB2UHzQw==" crossorigin="anonymous"></script>

如果某些对象有不同的键插入顺序,你想改变结果数组的顺序,或者如果你需要一些键,你可以用R.props获取值,然后转置:

const { pipe, map, props, transpose } = R;

const fn = pipe(
  map(props(['name', 'id'])), // example - name would be the 1st sub-array
  transpose,
);

const arr = [{"id":1,"name":"test"},{"id":2,"name":"test2"},{"id":3,"name":"test3"}];

const result = fn(arr);

console.log(result);
<script src="https://cdnjs.cloudflare.com/ajax/libs/ramda/0.27.1/ramda.min.js" integrity="sha512-rZHvUXcc1zWKsxm7rJ8lVQuIr1oOmm7cShlvpV0gWf0RvbcJN6x96al/Rp2L2BI4a4ZkT2/YfVe/8YvB2UHzQw==" crossorigin="anonymous"></script>

如果您想要 Scott Sauyet 建议的结构:

{
  id: [1, 2],
  name: ['test1', 'test2']
}

我会用 R.chain 和 R.toPairs 将对象映射并展平到一对数组中,按每对中的第一个项目(原始键)对它们进行分组,然后映射每个组每对中的项目到最后一项(原始值)。

const { pipe, chain, toPairs, groupBy, head, map, last } = R

const fn = pipe(
  chain(toPairs),
  groupBy(head),
  map(map(last)), // map(pipe(map(last), uniq)) if you want only unique items
) 

const arr = [{"id":1,"name":"test"},{"id":2,"name":"test2"},{"id":3,"name":"test3"}];

console.log(fn(arr))
<script src="//cdnjs.cloudflare.com/ajax/libs/ramda/0.27.1/ramda.js"></script>

正如 OriDrori 所指出的,您请求的输出不是有效的 JS。不过,关于它的一个有用的有效变体,我将做出稍微不同的猜测,即我们想要这样的输出:

{
  id: [1, 2],
  name: ['test1', 'test2']
}

这是在 vanilla JS 中实现这一点的一种简单方法:

const extract = (data) => {
  const keys = [... new Set (data .flatMap (Object .keys))]
  return Object .fromEntries (
    keys.map (k => [k, data .map (o => o [k])])
  )
}

const data = [{id: 1, name: "test"}, {id: 2, name: "test2"}]

console .log (
  extract (data)
)

我们绝对可以使用 Ramda 函数来清理它。另一个版本可能如下所示:

const extract = (data) => fromPairs (
  map (k => [k, map (o => o [k], data)]) (uniq (chain (keys) (data)))
)

const data = [{id: 1, name: "test"}, {id: 2, name: "test2"}]

console .log (extract (data))
<script src="https://cdnjs.cloudflare.com/ajax/libs/ramda/0.27.1/ramda.js"></script>
<script> const {fromPairs, map, uniq, chain, keys} = R                     </script>

虽然我们可以完全不加分,但我发现这个版本的可读性要差得多:

const extract = compose (
  fromPairs, 
  lift (map) (
    unary (compose (ap (pair), flip (pluck))), 
    compose (uniq, chain (keys))
  )
) 

const data = [
   {id: 1, name: "test"},
   {id: 2, name: "test2"}
]

console .log (extract (data))
<script src="//cdnjs.cloudflare.com/ajax/libs/ramda/0.27.1/ramda.js"></script>
<script> 
  const {compose, fromPairs, lift, map, unary, ap, pair, flip, pluck, uniq, chain, keys} = R 
</script>