繁体   English   中英

ramda.js:使用特定属性从对象数组中获取一组重复项

[英]ramda.js: obtain a set of duplicates from an array of objects using specific properties

给定此数组,包含javascript对象(json):
每个对象都有一个b属性和一个u属性,

(每个都包含我不关心此练习的其他属性)。

[
    { "b": "A", "u": "F", ... },
    { "b": "M", "u": "T", ... },
    { "b": "A", "u": "F", ... },
    { "b": "M", "u": "T", ... },
    { "b": "M", "u": "T", ... },
    { "b": "X", "u": "Y", ... },
    { "b": "X", "u": "G", ... },
]

我想使用ramda来查找所有重复项的集合。 结果看起来应该是这样的。

[ 
    { "b": "A", "u":"F" },
    { "b": "M", "u":"T" } 
]

这两个条目具有重复项,它们分别在原始列表中重复2次和3次。

编辑

我找到了一个使用下划线的解决方案,它保留了原始数组元素,并将它们完美地分成单个和重复。 我更喜欢ramda.js,并且下划线不仅仅提供一组重复 - 根据问题,所以我将问题保持开放,直到有人可以使用ramda回答。 我继续用下划线直到问题得到解答。

我有一个repl ,找到了独特的价值......作为一个开始......

这似乎过于复杂,不太可能具有高性能,但有一种选择:

const foo = pipe(
  project(['b', 'u']),
  reduce(
    ({results, foundOnce}, item) => contains(item, results)
      ? {results, foundOnce}
      : contains(item, foundOnce)
        ? {results: append(item, results), foundOnce}
        : {results, foundOnce: append(item, foundOnce)},
    {results: [], foundOnce: []}
  ), 
  prop('results')
)

foo(xs); //=> [{b: 'A', u: 'F'}, {b: 'M', u: 'T'}]

也许这个版本更容易理解,但需要额外迭代数据:

const foo = pipe(
  project(['b', 'u']),
  reduce(
    ({results, foundOnce}, item) => contains(item, foundOnce)
        ? {results: append(item, results), foundOnce}
        : {results, foundOnce: append(item, foundOnce)},
    {results: [], foundOnce: []}
  ),
  prop('results'),
  uniq
)

在这里复活

如果你不关心多次循环数据,你可能会这样:

  • 创建仅包含相关道具的部分副本,使用pick (您自己的想法)
  • 使用带有hash函数的groupBy来对相似的对象进行分组。 或者 :先sort并使用groupWith(equals)
  • 使用values获取分组数组
  • 筛选出数组只有1项使用(那些不上当......) filter
  • 映射结果并使用map(head)返回每个数组的第一个元素

在代码中:

const containsMoreThanOne = compose(lt(1), length);
const hash = JSON.stringify; // Naive.. watch out for key-order!

const getDups = pipe(
  map(pick(["b", "u"])),
  groupBy(hash),
  values,
  filter(containsMoreThanOne),
  map(head)
);

getDups(data);

Ramda REPL的工作演示。

一种更混合的方法是在一个减速器中扼杀所有这些逻辑,但它对我来说看起来有点混乱......

const clean = pick(["b", "u"]);
const hash = JSON.stringify;
const dupReducer = hash => (acc, o) => {
    const h = hash(o);
    // Mutate internal state
    acc.done[h] = (acc.done[h] || 0) + 1;
    if (acc.done[h] === 2) acc.result.push(o);

    return acc;
  };


const getDups = (clean, hash, data) =>
  reduce(dupReducer(hash), { result: [], done: { } }, map(clean, data)).result;

getDups(clean, hash, data);

REPL

  const arr = [];
  const duplicates = [];
  const values1 =  [
  { b: 'A', u: 'F', a: 'q' },
  { b: 'M', u: 'T', a: 'q' },
  { b: 'A', u: 'F', a: 'q' },
  { b: 'M', u: 'T', a: 'q' },
  { b: 'M', u: 'T', a: 'q' },
  { b: 'X', u: 'Y', a: 'q' },
  { b: 'X', u: 'G', a: 'q' },
 ];
 values1.forEach(eachValue => {
 arr.push(values(pick(['b', 'u'], eachValue)));
 });
 arr.forEach(fish => {
 if ( indexOf(fish, arr) !== lastIndexOf(fish, arr) ) {
   duplicates.push(zipObj(['b', 'u'], fish));
 }
});

[blog]: https://ramdafunctionsexamples.com/ "click here for updates"

<https://ramdafunctionsexamples.com/>?

不是Ramda JS的专家,但我认为以下内容应该有效:

var p = [
    { "b": "A", "u": "F" },
    { "b": "A", "u": "F" },
    { "b": "A", "u": "F" },
    { "b": "A", "u": "F" },
    { "b": "A", "u": "F" },
    { "b": "M", "u": "T" }
];
var dupl = n => n > 1;
R.compose(
    R.map(JSON.parse),
    R.keys,
    R.filter(dupl),
    R.countBy(String),
    R.map(JSON.stringify)
)(p)

如果有,请告诉我。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM