比较对象数组:Ramda方法

时间:2019-05-16 08:06:37

标签: javascript ramda.js

有2个对象数组,第一个是

const blocks = [
  { id: 1 },
  { id: 2 },
  { id: 3 },
]

第二个是

const containers = [
  { block: { id: 1 } },
  { block: { id: 2 } },
  { block: { id: 3 } },
]

我想获取blocks数组,从中获取每个对象,然后查找containers数组是否具有具有此类ID的块。因此,如果找不到至少一个ID,那么我想中断循环并返回false,否则,如果找到的所有ID都返回true。

我尝试使用.some()函数来实现这一点,但是当找不到id时我无法中断循环。

如果您建议Ramda做到这一点,我将不胜感激。

谢谢。

5 个答案:

答案 0 :(得分:1)

您可以使用R.differenceWith进行此操作:

const blocks = [
  { id: 1 },
  { id: 2 },
  { id: 3 },
];

const containers = [
  { block: { id: 1 } },
  { block: { id: 2 } },
  { block: { id: 4 } },
];

const diff = R.differenceWith((x,y) => x.id === y.block.id);
const mismatch = diff(blocks, containers).length > 0;

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

答案 1 :(得分:0)

以一种非ramda的方式,您可以将每个对象与其他项目进行比较,并进行深入检查。

const
    deep = id => o =>
        o && typeof o === 'object' && (o.id === id || Object.values(o).some(deep(id))),
    compare = (source, target) => source.every(({ id }) => target.some(deep(id))),
    blocks = [ { id: 1 }, { id: 2 }, { id: 3 }],
    containers = [{ block: { id: 1 } }, { block: { id: 2 } }, { block: { id: 3 } }]

console.log(compare(blocks, containers));

答案 2 :(得分:0)

您可以使用equals()方法。

const blocks = [
  { id: 1 },
  { id: 2 },
  { id: 3 },
]

const containers = [
  { block: { id: 1 } },
  { block: { id: 2 } },
  { block: { id: 3 } },
]

console.log(R.equals(containers.map(x => x.block.id),blocks.map(x => x.id)))
<script src="https://cdnjs.cloudflare.com/ajax/libs/ramda/0.26.1/ramda.js"></script>

答案 3 :(得分:0)

没有特定的Ramda Way TM 。 Ramda是一个库,一个工具箱,或者在Underscore的描述中是一个工具带。它的建立是为了使某种编码风格更易于在JS中读写。但这并不意味着完全决定如何编写代码。

Ramda的最大目标是通过组合功能来简化构建应用程序的过程,从而确保不可变性和引用透明性等FP优点。

因此,对于这个问题,我可能会从以下内容开始:

const hasBlock = (containers) => {
  const ids = containers .map (c => c.block.id)
  return (block) => ids .includes (block.id)
}

const allContained = (containers) => (blocks) => 
  blocks .every (hasBlock (containers) )

后一个功能可以使用Ramda快速重写为

const allContained = (containers) => (blocks) =>
  all(hasBlock(containers), blocks)

简化为

const allContained = (containers) => all(hasBlock(containers))

从那里到优雅:

const allContained = compose (all, hasBlock)

但是我看不到hasBlock的任何直接简化。我可能有一天会写成

const hasBlock = (containers, ids = containers .map (c => c.block.id) ) => 
  (block) => ids .includes (block.id)

但这只是为了满足内部对单表达式函数体的渴望,而不是出于任何真正好的理由。它并不能使代码更清晰,对于某些读者而言,它可能会使它更加晦涩难懂。

所以这就是我的结局:

const hasBlock = (containers) => {
  const ids = containers .map (c => c.block.id)
  return (block) => ids .includes (block.id)
}

const allContained = compose (all, hasBlock)

const containers = [{block: {id: 1}}, {block: {id: 2}}, {block: {id: 4}}]

console .log (
  allContained (containers) ([{id: 1}, {id: 2}, {id: 3}]), //=> false
  allContained (containers) ([{id: 1}, {id: 2}, {id: 4}]), //=> true
  allContained (containers) ([{id: 4}, {id: 1}]),          //=> true
  allContained (containers) ([{id: 42}]),                  //=> false
)
<script src="//cdnjs.cloudflare.com/ajax/libs/ramda/0.26.1/ramda.js"></script><script>
const {compose, all} = R      </script>

答案 4 :(得分:0)

您可以使用JS / Lodash / Ramda几乎完全相同的方法来实现此目的。

JS / Lodash对everysome具有完全相同的方法,在Ramda中对allany具有相同的方法:

const blocks = [{ id: 1 },{ id: 2 },{ id: 3 }]
const containers = [{ block: { id: 1 } },{ block: { id: 2 } },{ block: { id: 3 } }]

const blocks2 = [{ id: 1 },{ id: 2 },{ id: 3 }]
const containers2 = [{ block: { id: 4 } },{ block: { id: 2 } },{ block: { id: 3 } }]

let hasAllBlocks = (blks, conts) => 
   blks.every(b => conts.some(c => c.block.id === b.id))

let hasAllBlocksLD = (blks, conts) => 
  _.every(blks, b => _.some(conts, c => c.block.id === b.id))

let hasAllBlocksR = (blks, conts) => 
   R.all(b => R.any(c => c.block.id === b.id, conts), blks)

console.log(hasAllBlocks(blocks, containers))   // true
console.log(hasAllBlocks(blocks2, containers2)) // false

console.log(hasAllBlocksLD(blocks, containers))   // true
console.log(hasAllBlocksLD(blocks2, containers2)) // false

console.log(hasAllBlocksR(blocks, containers))   // true
console.log(hasAllBlocksR(blocks2, containers2)) // false
<script src="https://cdnjs.cloudflare.com/ajax/libs/ramda/0.25.0/ramda.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.11/lodash.min.js"></script>