Фильтрация и отображение массива с помощью Ramda - PullRequest
1 голос
/ 19 июня 2020

Я использую Ramda, чтобы получить команды с 'Prem League' в массиве категорий. Мой код выглядит следующим образом, и он работает.

import { pipe, map, filter } from 'ramda'   

const teams = [
  {name: 'Liverpool', id: '1', categories: ['Prem League']},
  {name: 'Man Utd', id: '2', categories: ['Blue Square']},
  {name: 'Sheff Utd', id: '2', categories: ['Prem League']},
]

const getTeamOptions = pipe(
    filter((team) => team.categories.includes('Prem League')),
    map((team) => ({ label: team.name, value: team.id }))
);

getTeamOptions(teams)

Однако я хочу удалить team в качестве аргумента для фильтра и map.

Я пробовал следующее, но получил prop(...).includes is not a function

filter(prop('categories').includes('Prem League')),

В идеале я бы попытался удалить team из map, но, возможно, в этом нет необходимости.

Причина этих изменений в том, что я следил этот курс и советует prop и c в качестве передового опыта.

Ответы [ 5 ]

1 голос
/ 20 июня 2020

это также поможет вам решить эту проблему с помощью ramda без использования очков ...

const hasPremLeague = R.where({ categories: R.includes('Prem League') });
const toOption = R.applySpec({ label: R.prop('name'), value: R.prop('id') });

const getTeamOptions = R.into([], R.compose(
  R.filter(hasPremLeague), 
  R.map(toOption),
));

// ---

const teams = [
  {name: 'Liverpool', id: '1', categories: ['Prem League']},
  {name: 'Man Utd', id: '2', categories: ['Blue Square']},
  {name: 'Sheff Utd', id: '2', categories: ['Prem League']},
];

console.log(
  getTeamOptions(teams),
);
<script src="https://cdnjs.cloudflare.com/ajax/libs/ramda/0.27.0/ramda.js"></script>
1 голос
/ 19 июня 2020

Вы можете использовать R.includes, чтобы проверить наличие значения. Вы можете сгенерировать новый объект, используя R.applySpe c:

const { pipe, filter, prop, includes, map, applySpec } = R;

const getTeamOptions = val => pipe(
  filter(pipe(prop('categories'), includes(val))),
  map(applySpec({ label: prop('name'), value: prop('id') }))
);

const teams = [{"name":"Liverpool","id":"1","categories":["Prem League"]},{"name":"Man Utd","id":"2","categories":["Blue Square"]},{"name":"Sheff Utd","id":"2","categories":["Prem League"]}];

const result = getTeamOptions('Prem League')(teams);

console.log(result);
<script src="https://cdnjs.cloudflare.com/ajax/libs/ramda/0.27.0/ramda.js"></script>
0 голосов
/ 03 июля 2020

Мне нравится делать это компонуемым способом, но в настоящее время вы используете pipe, поэтому я делаю это с pipe для согласованности. Ниже проработанное решение

const teams = [
  { name: 'Liverpool', id: '1', categories: ['Prem League'] },
  { name: 'Man Utd', id: '2', categories: ['Blue Square'] },
  { name: 'Sheff Utd', id: '2', categories: ['Prem League'] }
]

const getTeamOptions = pipe(
  filter(
    pipe(
      prop('categories'),
      includes('Prem League')
    )
  ),
  map(
    pipe(
      props(['name', 'id']),
      zipObj(['label', 'value'])
    )
  )
)

console.log(getTeamOptions(teams))
<script src="https://cdnjs.cloudflare.com/ajax/libs/ramda/0.27.0/ramda.js"></script>
<script>const { pipe, map, filter, prop, includes, zipObj, props } = R</script>
0 голосов
/ 19 июня 2020

Вам также следует рассмотреть вариант без Ramda.

Это может быть или не быть злоупотреблением Array#flatMap, но я считаю это приемлемым: filter + map = flatMap

Допустим, вы хотите прибавить 10 к четным числам и исключить нечетные числа:

[1, 2, 3, 4].flatMap(n => n % 2 === 0 ? n + 10 : []);
//=> [12, 14]

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

const getTeamOptions =
  teams =>
    teams.flatMap
      ( ({name: label, id: value, categories}) =>
          categories.includes('Prem League')
            ? { label, value }
            : []
      );

getTeamOptions
  ( [ {name: 'Liverpool', id: '1', categories: ['Prem League']}
    , {name: 'Man Utd', id: '2', categories: ['Blue Square']}
    , {name: 'Sheff Utd', id: '2', categories: ['Prem League']}
    ]
  );

//=> [ {label: "Liverpool", value: "1"}
//=> , {label: "Sheff Utd", value: "2"} ]

Для полноты, вот вариант с использованием Array#reduce:


const getTeamOptions =
  teams =>
    teams.reduce
      ( (acc, {name: label, id: value, categories}) =>
          categories.includes('Prem League')
            ? (acc.push({ label, value }), acc)
            : acc
      , []
      );

Не поймите меня неправильно! Рамда абсолютно потрясающе . Когда я впервые встретил эту библиотеку, мне захотелось переписать с ней весь свой код, потом я открыл для себя безточечный стиль и снова все переписал. В конце концов, я полностью потерял мысленный контроль над своим кодом, и это проблема. Вам следует использовать Ramda только тогда, когда она вам хорошо служит. В этом случае, если честно, можно обойтись и без.

0 голосов
/ 19 июня 2020
const premLeague = R.equals('Prem League');
const premLeagueInArray = R.any(premLeague);
const categories = R.path(['categories']);
const isPremLeagueInArray = R.pipe(
  categories,
  premLeagueInArray,
);

const teams = [
  { name: "Liverpool", id: "1", categories: ["Prem League"] },
  { name: "Man Utd", id: "2", categories: ["Blue Square"] },
  { name: "Sheff Utd", id: "2", categories: ["Prem League"] },
];
const premLeagueTeam = [
  { name: "Liverpool", id: "1", categories: ["Prem League"] },
  { name: "Sheff Utd", id: "2", categories: ["Prem League"] },
];

const transducer = R.compose(R.filter(isPremLeagueInArray));
const getPremLeagueTeam = R.transduce(transducer, R.flip(R.append), []);

R.equals(getPremLeagueTeam(teams), premLeagueTeam);
...