Пожалуйста, как мне добиться следующего с помощью ramda - PullRequest
1 голос
/ 21 апреля 2020

У меня есть случайный массив чисел от 1 до 5, встречающийся иногда в случайных случаях [1,1,1,1,2,2] et c. Передо мной стоит задача найти значение с наивысшим значением в любое время, независимо. Я достиг этого в javascript, как показано ниже, используя библиотеку ramda здесь . Прочитав документацию, я выбрал решение, подобное приведенному ниже.

// filter out duplication in array that way you can get the uniq represented numbers
const uniqueItems = R.uniq(params);

// use the unique numbers as keys and create a new array of object
 const mappedItemsWithRepresentations = map((a) => ({ color: a, rep: params.filter(b => b === a).length }), uniqueItems);

// and then finally, select the item with highest rep and return it key
const maxRepItem = mappedItemsWithRepresentations.reduce((acc, curr) => acc.rep > curr.rep ? acc : curr, []);

return maxRepItem.key; // gives me the correct value i need

Однако, прочитав больше в документации и пройдясь по примеру здесь , я понял, что есть способ, которым я можно комбинировать логи c выше и просто с рамдой. Я попробовал множество возможных попыток, и ближайший, который я смог получить, был ниже.

const getMaxRep = curry(pipe(uniq, map((a) => ({ color: a, rep: filter(b => b === a).length })), pipe(max(pathEq("rep")), tap(console.log))));

console.log("Max Rep here", getMaxRep(params));

Я также попытался использовать уменьшенную функцию здесь , но все безрезультатно. Пожалуйста, как мне это сделать? Любая помощь будет оценена.

Ответы [ 3 ]

2 голосов
/ 21 апреля 2020

У Рамды есть R.countBy для получения количества вхождений. Вы можете преобразовать полученный объект страны в пары [value, count], а затем уменьшить его, чтобы найти пару с наибольшим количеством:

const { pipe, countBy, identity, toPairs, reduce, maxBy, last, head } = R

const fn = pipe(
  countBy(identity), // count the occurrences 
  toPairs, // convert to pairs of [value, count]
  reduce(maxBy(last), [0, 0]), // reduce to find the maximum occurrence
  head, // get the actual value
  Number, // convert back to an number
)

const arr = [1,1,1,1,2,2]

const result = fn(arr)

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

Небольшое отклонение от этой идеи, которая собирает значения с одинаковым количеством в массив. Это будет обрабатывать случаи, в которых частота нескольких предметов идентична:

const { pipe, countBy, identity, toPairs, invert, reduce, maxBy, last, head, map } = R

const fn = pipe(
  countBy(identity), // count the occurrences 
  invert, // combine all values with the same count
  toPairs, // convert to pairs of [value, count]
  reduce(maxBy(head), [0, 0]), // reduce to find the maximum occurrence
  last, // get the actual values
  map(Number), // convert back to numbers
)

const arr = [1,1,1,1,2,2,3,3,3,3]

const result = fn(arr)

console.log(result)
<script src="https://cdnjs.cloudflare.com/ajax/libs/ramda/0.27.0/ramda.js"></script>
1 голос
/ 21 апреля 2020

Мне не совсем понятно, о чем вы просите.

Но это может быть что-то вроде этого:

const maxRep = pipe (
  countBy (identity),
  toPairs,
  map (zipObj(['color', 'rep'])), 
  reduce (maxBy (prop ('rep')), {rep: -Infinity}),
)

const params = [1, 2, 3, 4, 2, 3, 5, 2, 3, 2, 1, 1, 4, 5, 5, 3, 2, 5, 1, 5, 2]

console .log (
  maxRep (params)
)
<script src="//cdnjs.cloudflare.com/ajax/libs/ramda/0.27.0/ramda.js"></script>
<script> const {pipe, countBy, identity, toPairs, map, zipObj, reduce, maxBy, prop} = R </script>

Мы начнем со списка значений, взятых из {1, 2, 3, 4, 5}, происходящих в некотором случайном многократном порядке.

С countBy(identity) мы изменяем исходный список на что-то вроде

{"1": 4, "2": 6, "3": 4, "4": 2, "5": 5}

со счетчиками, связанными с каждой записью.

toPairs форматирует этот массив как

[["1", 4], ["2", 6], ["3", 4], ["4", 2], ["5", 5]]

(Вы также можете использовать Object.entries здесь.)

Затем, вызывая map (zipObj (['color', 'rep'])), мы превращаем это в

[{"color": "1", "rep": 4}, {"color": "2", "rep": 6}, ...]

Наконец, мы уменьшаем результат, используя maxBy (prop ('rep')), что выбирает тот с максимальным значением повторения. Для начального значения для вызова max мы создаем фиктивный объект {rep: -Infinity}, который будет сравнивать меньше, чем любой в вашем списке.

Если вы хотите также сохранить эту окончательную промежуточную структуру, вы можете переименовать эту функцию на makeReps, сбросив последнюю функцию в конвейере, а затем сделав из нее новую maxRep.

Затем вы можете вызвать

const reps = makeResps (params)
const maxVal = maxRep (reps)

и использовать обе.

Но все это предполагает, что вам нужно значение со свойствами color и rep. Если вам просто нужен подсчет, то другие решения, которые уже здесь, справятся с этим.

1 голос
/ 21 апреля 2020

хороший вариант использования, попробуйте это:

const maxReduce = reduce(maxBy(last), [0,0])
const getMaxRep = pipe(countBy(identity), toPairs, maxReduce, head)

console.log(getMaxRep([1,1,1,1,2,2]))

countBy - действительно хорошее начало, к сожалению, Ramda не поддерживает сокращение для объекта, но мы можем преобразовать в массив массивов, используя функцию toPairs и fini sh работа.

...