immutable.js 过滤和变异(删除)找到的条目

Posted

技术标签:

【中文标题】immutable.js 过滤和变异(删除)找到的条目【英文标题】:immutable.js filter and mutate (remove) found entries 【发布时间】:2017-04-06 12:18:15 【问题描述】:

我有两个循环,一个用于一个月中的每一天,另一个用于本月的所有事件。假设我有 100 000 个事件。 我正在寻找一种方法从主要事件List 中删除事件,一旦它们被“消耗”。

代码是这样的:

const calendarRange = [initialDate, initialDate, initialDate, initialDate, ...] // say we have 30 dates, one for each day
const events = fromJS([initialDate, initialDate, initialDate, ...]) // let's say we have 100 000
calendarRange.map((day) => 
  const dayEvents = events.filter((event) => day.get('initialDate').isSame(event.get('initialDate'), 'day')) // we get all events for each day 
  doSomeThingWithDays(dayEvents)
  // how could I subtract `dayEvents` from `events` in a way
  // the next celandarRange iteration we have less events to filter? 
  // the order of the first loop must be preserved (because it's from day 1 to day 301])

使用 lodash 我可以做类似的事情:

calendarRange.map((day) => 
  const dayEvents = events.filter((event) => day.get('initialDate').isSame(event.get('initialDate'), 'day')) // we get all events for each day 
  doSomeThingWithDays(dayEvents)
  pullAllWith(events, dayEvents, (a, b) => a === b)

如何用 immutablejs 完成同样的优化?我并不是真的期待我的迭代列表方式的解决方案,而是一种智能的方式来减少事件List,使其变得越来越小..

【问题讨论】:

【参考方案1】:

您可以尝试Map 将事件拆分为垃圾箱-根据您的示例,您可以根据日期进行垃圾箱-您可以查找垃圾箱,将其作为批处理并将其删除 O(1)。不可变映射相当便宜,而且比遍历列表要好得多。您可能会产生一次性分箱的成本,但可以通过 O(1) 查找来分期付款。

可能是这样的:

eventbins = OrderedMap(events.groupBy(evt => evt.get('initialDate').dayOfYear() /* or whatever selector */)) 

function iter(list, bins)  
 if(list.isEmpty()) 
   return
 day = list.first()
 dayEvents = bins.get(day.dayOfYear())
 doSomeThingWithDays(dayEvents)
 iter(list.shift(), bins.delete(day))


iter(rangeOfDays, eventbins)

【讨论】:

顺便说一句,我应该补充一点,该方法是纯函数式的,具有零副作用并使用尾递归。如果你想,说其余的项目,你可以简单地从iter返回一个值。【参考方案2】:

通过移除已经处理过的元素,你不会让任何事情变得更快。所有过滤器操作的成本平均会减半,但是在每次迭代中构建新列表会花费你一些 cpu 周期,因此它不会显着加快(在大 O 意义上)。相反,您可以基于 initialDate-s 构建索引,例如不可变映射,从而使所有 filter 调用变得不必要。

const calendarRange = Immutable.Range(0, 10, 2).map(i => Immutable.fromJS(initialDate: i));

const events = Immutable.Range(0, 20).map(i => Immutable.fromJS(initialDate: i%10, i:i));


const index = events.groupBy(event => event.get('initialDate'));

calendarRange.forEach(day => 
  const dayEvents = index.get(day.get('initialDate'));
  doSomeThingWithDays(dayEvents);
);

function doSomeThingWithDays(data) 
  console.log(data);
<script src="https://cdnjs.cloudflare.com/ajax/libs/immutable/3.8.1/immutable.js"></script>

【讨论】:

以上是关于immutable.js 过滤和变异(删除)找到的条目的主要内容,如果未能解决你的问题,请参考以下文章

如何纠正 R 函数中的变异和过滤错误

使用过滤器/变异和 dplyr/tidyverse 逻辑对数据库进行分类[重复]

使用 immutable.js 和 Facebook 流进行静态类型检查

immutable-js基础

如何在 immutable.js 中定义字符串和数字数组或元组

Immutable.js 与 Angular 2