Ramda GroupBy - Как группировать по любой опоре - PullRequest
4 голосов
/ 18 июня 2019

Дано:

interface Dict {
  [key: string]: any
}

const data: Dict[] = [
  { id: 'a' },
  { id: 'b', b: 'something' },
  { id: 'c', b: 'else' },  
  { id: 'd', extra: 'hello world' },
  { id: 'e' },  
];

где ключи этих Dict объектов не указаны ...

Как мне получить этот результат?

const result = {
  id: ['a', 'b', 'c', 'd', 'e'],
  b: ['something', 'else'],
  extra: ['hello world'],
  // ... and any other possible key
}

Ответы [ 3 ]

4 голосов
/ 18 июня 2019

Вы можете объединить объект в список пар, сгруппировать его и преобразовать пары обратно в значения:

const data = [
  { id: 'a' },
  { id: 'b', b: 'something' },
  { id: 'c', b: 'else' },  
  { id: 'd', extra: 'hello world' },
  { id: 'e' },  
];


let z = R.pipe(
  R.chain(R.toPairs),
  R.groupBy(R.head),
  R.map(R.map(R.last))
)

console.log(z(data))
<script src="https://cdnjs.cloudflare.com/ajax/libs/ramda/0.26.1/ramda.js"></script>
3 голосов
/ 18 июня 2019

Небольшое отклонение от ответа Ори Дрори: (при условии, что никакие свойства ваших объектов уже не содержатся в массивах)

const data = [
  { id: 'a' },
  { id: 'b', b: 'something' },
  { id: 'c', b: 'else' },  
  { id: 'd', extra: 'hello world' },
  { id: 'e' }
];

const run = reduce(useWith(mergeWith(concat), [identity, map(of)]), {});

console.log(
  run(data)
)
<script src="https://cdnjs.cloudflare.com/ajax/libs/ramda/0.26.1/ramda.min.js"></script>
<script>const {reduce, useWith, mergeWith, concat, identity, map, of} = R;</script>
2 голосов
/ 18 июня 2019

Используйте R.reduce с R.mergeWith и объедините все элементы:

const { mergeWith, reduce } = R

const fn = reduce(mergeWith((a, b) => [].concat(a, b)), {})


const data = [
  { id: 'a' },
  { id: 'b', b: 'something' },
  { id: 'c', b: 'else' },  
  { id: 'd', extra: 'hello world' },
  { id: 'e' },  
];

const result = fn(data)

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

Если вам нужно также одно значение (extra) в массиве, сопоставьте элементы и оберните массивом, только значения, которые не являютсямассив уже:

const { pipe, mergeWith, reduce, map, unless, is, of } = R

const fn = pipe(
  reduce(mergeWith((a, b) => [].concat(a, b)), {}),
  map(unless(is(Array), of))
)


const data = [
  { id: 'a' },
  { id: 'b', b: 'something' },
  { id: 'c', b: 'else' },  
  { id: 'd', extra: 'hello world' },
  { id: 'e' },
];

const result = fn(data)

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