使用ramda`sequence`来遍历字典

时间:2017-11-14 18:11:59

标签: ramda.js fantasyland

如何使用ramda' sequence遍历字典?

给出以下字典

cars = {color: ['yellow', 'red'], year: [2017], model: ['coup', 'sedan']}

我想生成遍历结果

all_cars = [
    {color: 'yellow', year: 2017, model: 'coup'},
    {color: 'yellow', year: 2017, model: 'sedan'},
    {color: 'red', year: 2017, model: 'coup'},
    {color: 'red', year: 2017, model: 'sedan'}
]

使用R.sequence会产生一个空列表列表

R.sequence(R.of, cars)
[[]]

如果我遍历列表而不是字典,它会生成正确的笛卡尔积,但结果是(当然)列表而不是字典。

R.sequence(R.of, [['yellow', 'red'], [2017], ['coup', 'sedan']])
[["yellow", 2017, "coup"], ["yellow", 2017, "sedan"], ["red", 2017, "coup"], ["red", 2017, "sedan"]]

1 个答案:

答案 0 :(得分:1)

我可以想到两种方法,一种涉及sequence,另一种不涉及。

这个使用上面的sequence(of)电话:

const convert = lift(map)(
  compose(zipObj, keys), 
  compose(sequence(of), values)
)

const all_cars = convert(cars);

另一个是我通常的技术建立的,一个接一个地改变输出,直到我得到我想要的东西:

const combine = pipe(
  toPairs,
  map(apply(useWith(map, [objOf, identity]))),
  reduce(xprod, [[]]),
  map(flatten),
  map(mergeAll)
)

const all_cars = combine(cars)

通过在多个列表中引入交叉产品,可以更清楚一点:

const xproduct = reduce(pipe(xprod, map(unnest)), [[]])

const combine = pipe(
  toPairs,
  map(apply(useWith(map, [objOf, identity]))),
  xproduct,
  map(mergeAll)
)

第二个版本是我在第一次尝试问题时提出的。然后当我看到你尝试过的时候,我得到了第一个版本。第一个版本对我来说看起来更干净,尽管第二个版本中的大多数单独步骤都是微不足道的。但是由于那里有一个非常重要的步骤,第一个似乎是一个总冠军。

您可以在Ramda REPL上看到the firstthe second