Отфильтруйте уникальные вложенные значения с помощью ramda - PullRequest
0 голосов
/ 19 октября 2018

У меня есть коллекция меток времени UNIX, которая выглядит следующим образом:

[
  {"start_time":1540458000000, "end_time":1540472400000}, 
  {"start_time":1540458000000, "end_time":1540486800000}, 
  {"start_time":1540458000000, "end_time":1540501200000}, 
  {"start_time":1540472400000, "end_time":1540486800000}, 
  {"start_time":1540472400000, "end_time":1540501200000}, 
  {"start_time":1540486800000, "end_time":1540501200000}
]

Я бы хотел выбрать все уникальные значения как start_time, так и end_time, так что я осталсяс:

[
  {"start_time":1540458000000}, 
  {"start_time":1540472400000}, 
  {"start_time":1540486800000}
  {"end_time":1540472400000},
  {"end_time":1540486800000}, 
  {"end_time":1540501200000}, 
]

Я смотрел на использование чего-то подобного, используя groupBy, pluck, zipObj и более, используя ответ здесь .Но без удачи, к сожалению.

Приятно было бы иметь функцию ramda, которая работала бы без необходимости давать конкретные ключи.

Ответы [ 3 ]

0 голосов
/ 19 октября 2018

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

const { pipe, map, toPairs, transpose, uniqBy, last, unnest, objOf, apply } = R;

const data = [
  {"start_time":1540458000000, "end_time":1540472400000}, 
  {"start_time":1540458000000, "end_time":1540486800000}, 
  {"start_time":1540458000000, "end_time":1540501200000}, 
  {"start_time":1540472400000, "end_time":1540486800000}, 
  {"start_time":1540472400000, "end_time":1540501200000}, 
  {"start_time":1540486800000, "end_time":1540501200000}
];

const getUniqueProps =
  pipe(
    map(toPairs),
    transpose,
    map(uniqBy(last)),
    unnest,
    map(apply(objOf))
  );
  
console.log(getUniqueProps(data));
<script src="https://cdnjs.cloudflare.com/ajax/libs/ramda/0.25.0/ramda.min.js"></script>

Если вы знаете свойства, которые вам нужны, вы можете groupBy свойство, получить первый объект из каждой группы, а затем выбрать свойство, из которого вы хотитекаждый объект:

const { groupBy, prop, concat, pipe, map, head, pick, values } = R;

const data = [
  {"start_time":1540458000000, "end_time":1540472400000}, 
  {"start_time":1540458000000, "end_time":1540486800000}, 
  {"start_time":1540458000000, "end_time":1540501200000}, 
  {"start_time":1540472400000, "end_time":1540486800000}, 
  {"start_time":1540472400000, "end_time":1540501200000}, 
  {"start_time":1540486800000, "end_time":1540501200000}
];

const getUniqueProp = (propName) =>
  pipe(
    groupBy(prop(propName)),
    map(pipe(head, pick([propName]))),
    values,
  );
  
const getStartEnd = (data) => concat(
  getUniqueProp('start_time')(data),
  getUniqueProp('end_time')(data),
);

console.log(getStartEnd(data));
<script src="https://cdnjs.cloudflare.com/ajax/libs/ramda/0.25.0/ramda.min.js"></script>
0 голосов
/ 19 октября 2018

Другой подход Рамды:

const {pipe, map, toPairs, unnest, groupBy, head, uniqBy, last, values, apply, objOf} = R

const uniqTimes = pipe(
  map(toPairs),          //=> [[['start', 1], ['end', 2]], [['start', 1], ['end', 3]], ...]
  unnest,                //=> [['start', 1], ['end', 2], ['start', 1], ['end', 3], ...]
  groupBy(head),         //=> {start: [['start', 1], ['start', 1], ['start', 4], ...], end: [['end', 2], ...]}
  map(uniqBy(last)),     //=> {start: [['start', 1], ['start', 4], ...], end: [['end', 2], ...]}
  values,                //=> [[['start', 1], ['start', 4], ...], [['end', 2], ...]]
  unnest,                //=> [['start', 1], ['start', 4], ..., ['end', 2], ...]
  map(apply(objOf))      //=> [{"start": 1}, {"start": 4}, ..., {"end": 2}, ...]
)

const timestamps = [{"start_time":1540458000000,"end_time":1540472400000},{"start_time":1540458000000,"end_time":1540486800000},{"start_time":1540458000000,"end_time":1540501200000},{"start_time":1540472400000,"end_time":1540486800000},{"start_time":1540472400000,"end_time":1540501200000},{"start_time":1540486800000,"end_time":1540501200000}]

console.log(uniqTimes(timestamps))
<script src="//cdnjs.cloudflare.com/ajax/libs/ramda/0.25.0/ramda.js"></script>

Вот как мне нравится использовать Ramda: создать конвейер функций, каждая из которых выполняет простые преобразования.


Обновление

В комментарии был задан вопрос о том, как сгенерировать вывод, похожий на

{
   "start_time": [1540458000000, 1540458000000],
   "end_time": [1540472400000, 1540486800000]
}

Это должно быть сделано для того же ввода:

const uniqTimes = pipe(
  map(toPairs), 
  unnest,
  groupBy(head),
  map(map(last)),
  map(uniq)
)
0 голосов
/ 19 октября 2018

Не уверен насчет ramda, но ниже обычная функция js сделает это

const arr = [
  {"start_time":1540458000000, "end_time":1540472400000}, 
  {"start_time":1540458000000, "end_time":1540486800000}, 
  {"start_time":1540458000000, "end_time":1540501200000}, 
  {"start_time":1540472400000, "end_time":1540486800000}, 
  {"start_time":1540472400000, "end_time":1540501200000}, 
  {"start_time":1540486800000, "end_time":1540501200000}
];

function foo(arr) {
  return [...arr.reduce((a, b) => {
    Object.entries(b).forEach(e => a.set(String(e), e));
    return a;
  }, new Map())].map(([_,e]) => ({
  	[e[0]]: e[1]
  }))
}

console.log(foo(arr));
...