ramda.js - lambda : Split a list to segments

标签 ramda.js

如果我们有一个列表,例如:

[
  {
    type: 'a',
  },
  {
    type: 'a',
  },
  {
    type: 'b',
  },
  {
    type: 'a',
  }
]

...我们想要将其分段以创建一个列表,这样新列表由初始列表的每个段组成,这里按类型拆分,如下所示:

[
  [
    {
      type: 'a',
    },
    {
      type: 'a',
     },
  ],
  [
    {
      type: 'b',
    },
  ],
  [
    {
      type: 'a',
    }
  ]
]

我想创建一个通用的“分段”函数,它使用一个函数来比较两个项目,并确定是否需要新的分段。在这里,该函数的“分段器”只是比较类型。

我可以用普通的 JavaScript 编写,但是有没有一个好的方法可以用 Ramda 来做到这一点

const data = [
  {
    type: 'a',
  },
  {
    type: 'a',
  },
  {
    type: 'b',
  },
  {
    type: 'a',
  }
];

const segmentBy = segmenter => items => {
  const segmentReducer = (prev = [], curr) => {
    let lastSegment = [];
    let lastItem = null;
    
    try {
      lastSegment = prev[prev.length - 1];
      lastItem = lastSegment[lastSegment.length - 1];
    } catch (e) {
      return [...prev, [curr]];
    }
    const requiresNewSegment = segmenter(lastItem, curr);
    
    if (requiresNewSegment) {
      return [...prev, [curr]];
    }
    
    return [...prev.slice(0, prev.length - 1), [...lastSegment, curr]];
  };
  
  return items.reduce(segmentReducer, []);
};

const segmentByType = segmentBy((a, b) => a.type !== b.type);
const segments = segmentByType(data);
  
console.dir(segments);

最佳答案

通过 Ramda,您可以使用 R.groupWith:

Takes a list and returns a list of lists where each sublist's elements are all satisfied pairwise comparison according to the provided function. Only adjacent elements are passed to the comparison function.

const data = [{"type":"a"},{"type":"a"},{"type":"b"},{"type":"a"}];

const segmentByType = R.groupWith(R.eqBy(R.prop('type')));
const segments = segmentByType(data);
  
console.dir(segments);
<script src="https://cdnjs.cloudflare.com/ajax/libs/ramda/0.26.1/ramda.js"></script>

在 vanilla 中,主要问题是何时向累加器添加新的子数组。当它是第一项时,或者 segmenter 返回 true 时,您需要添加另一个子数组。

const data = [{"type":"a"},{"type":"a"},{"type":"b"},{"type":"a"}];

const segmentBy = segmenter => items =>
  items.reduce((r, item, i, arr) => {
    if(i === 0 || segmenter(item, arr[i - 1])) r.push([]);
    
    r[r.length - 1].push(item);
    
    return r;
  }, []);

const segmentByType = segmentBy((a, b) => a.type !== b.type);
const segments = segmentByType(data);
  
console.dir(segments);

关于ramda.js - lambda : Split a list to segments,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/56235275/

相关文章:

javascript - 如何从 Crocks javascript 库中的 Monads 中提取值

angular - 找不到 'ramda' 的类型定义文件

javascript - 如何使用带多个参数的 R.pipe?

javascript - 尝试重构此代码以仅使用不可变结构

javascript - lambda 斯 : locating items with an inner array that satisfies a spec

javascript - 将对象的每个值称为 pointfree

javascript - 如何使用 Ramda remove 从对象数组中删除空对象?

javascript - 如何使用无点递归实现使用 Ramda 删除对象中的空值?

ramda.js - 如何使用ramdajs同时更改多个值

javascript - 如何将这个为每个对象添加键的_.each函数转换为Ramda?