Головоломка программирования без очков - PullRequest
1 голос
/ 06 ноября 2019

У меня есть функция, которая, написанная с помощью анонимных функций, будет гидрировать массив идентификаторов, используя список объектов, соответствующих свойству id.

const objectsList = [{ id: 1, ... }, { id: 2, ... }]
ids.map(id => R.find(R.propEq('id', id), objectsList))

(я знаю, что глупо смотретьтаким образом - неэффективно и т. д. - давайте на данный момент проигнорируем это.)

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

ids.map(R.find(R.propEq('id', R.__), objects))

Но это не хорошо. Я также попытался изменить порядок параметров и использовать compose, но это не дало правильного результата:

ids.map(R.compose(R.flip(R.find)(objects), R.propEq('id')))

Это тоже не игра в кости ... Любой волшебник FP хочет помочь тому, кто всегда пытаетсявыяснить нюансы бессмысленного программирования?

ОБНОВЛЕНИЕ

Спасибо тем, кто ответил! Согласованное, бессмысленное программирование не должно быть фетишизированным;в основном я просил углубить мое понимание FP и инструментов Ramda. Я согласен со всеми постерами, что бессмысленное программирование не должно расставляться по приоритетам над читабельностью.

Я определенно узнал намного больше о Рамде благодаря этому, и надеюсь, что некоторые другие также поступят так же. : -)

Ответы [ 3 ]

3 голосов
/ 06 ноября 2019

Редактировать

Обратите внимание, что часть текста здесь основана на другом ответе, который использовал эту версию: innerJoin(useWith(equals, [prop('id'), identity])). Этот ответ был улучшен и больше не использует эту технику. Но эти комментарии по-прежнему имеют смысл сами по себе.


Я бы посоветовал вам не делать фетиш из бессмысленного программирования, а использовать его только там, где он улучшает читабельность.

Мне кажется, что этот вариант ответа от OriDrori гораздо легче читать:

const extractMatches = R.innerJoin ((o, id) => o.id === id)

const objectsList = [{ id: 1, x: 'a' }, { id: 2, x: 'b' }, { id: 3, x: 'c' }, { id: 4, x: 'd' }, { id: 5, x: 'e' }]
const ids = [1, 2, 4]

console .log (
  extractMatches (objectsList, ids)
)
<script src="//cdnjs.cloudflare.com/ajax/libs/ramda/0.26.1/ramda.js"></script>

Даже если бы существовала какая-то бессмысленная версия, в которой не использовался тяжелый и несколько не интуитивно понятный Рамда useWith, сделать его более читабельным довольно сложно. чем та, что выше на одну строчку.

useWith было написано, когда многие пользователи Ramda были все еще на ES5 (или даже на ES3!). Это редко кажется мне хорошим выбором в наши дни. Единственное, что он добавляет, - это возможность писать без очков, и обычно это затеняет вещи. (Отказ от ответственности: я один из основателей Ramda и большой поклонник, но не каждая функция получает равную любовь!)

2 голосов
/ 06 ноября 2019

РЕДАКТИРОВАТЬ: Как указал Скотт, я не внимательно прочитал этот вопрос. Это не стиль без очков, и я не думаю, что достижение решения без очков - это хорошая идея. Вариант Скотта с ответом Ори Дрори выглядит хорошо для меня

Я бы перефразировал проблему: «Учитывая список объектов, оставляйте только те, идентификаторы которых находятся в белом списке»

Учитывая эти объекты:

const objects = [{id: 1, title: 'foo'}, {id: 2, title: 'bar'}];

И этот белый список:

const whitelist = [2];

Тогда вы можете сделать:

const inArray = flip(includes);
filter(propSatisfies(inArray(whitelist), 'id'), objects);
//=> [{"id": 2, "title": "bar"}]
2 голосов
/ 06 ноября 2019

Вам нужно ограничить арность функции до 1 с помощью R.unary, поскольку Array.map() передает 3 параметра в обратный вызов (значение, индекс, исходный массив). R.propEq ожидает 3 параметра, и значения, переданные обратному вызову карты, заполняют их, функция вызывается, и R.find получает результаты, а не функцию.

const objectsList = [{ id: 1 }, { id: 2 }]
const ids = [2]

const fn = R.unary(R.compose(R.flip(R.find)(objectsList), R.propEq('id')))

const result = ids.map(fn)

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

Если вы хотите отказаться от Array.map() и создать функцию без точек, вы можете использовать R.innerJoin. Для создания предиката используйте перевернутый R.propEq('id'):

const { innerJoin, flip, propEq } = R

const fn = innerJoin(flip(propEq('id')))

const objectsList = [{ id: 1 }, { id: 2 }]
const result = fn(objectsList, [2])
console.log(result)
<script src="https://cdnjs.cloudflare.com/ajax/libs/ramda/0.26.1/ramda.js"></script>
...