immutable.js 过滤并改变(删除)找到的条目
immutable.js filter and mutate (remove) found entries
我有两个循环,一个用于每个月的每一天,另一个用于本月的所有事件。假设我有 100 000 个事件。
我正在寻找一种方法来从主要事件 List
中删除事件,一旦它们是 "consumed"。
代码类似于:
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 3{01}])
}
使用 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
以一种越来越小的方式..
您可以尝试 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)
移除已经处理过的元素不会使任何事情变得更快。所有过滤器操作的成本将平均减半,但在每次迭代中构建新列表将花费您一些 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>
我有两个循环,一个用于每个月的每一天,另一个用于本月的所有事件。假设我有 100 000 个事件。
我正在寻找一种方法来从主要事件 List
中删除事件,一旦它们是 "consumed"。
代码类似于:
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 3{01}])
}
使用 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
以一种越来越小的方式..
您可以尝试 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)
移除已经处理过的元素不会使任何事情变得更快。所有过滤器操作的成本将平均减半,但在每次迭代中构建新列表将花费您一些 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>