2016-11-22 40 views
8

我有兩個循環,一個爲每個月的一天,其他與本月的所有事件。假設我有100 000個事件。 我正在尋找一種方法,在主要事件List「一旦消耗」時刪除事件。immutable.js過濾器和mutate(刪除)找到的條目

的代碼是一樣的東西:

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在一種方式,它變得越來越小...

回答

4

你可以嘗試一個Map事件拆分爲箱 - 基於你的例子,你基於日期的bin - 你可以查找一個bin,把它作爲一個批處理並將其移除(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) 
+0

順便說一句,我要補充,該方法是純功能與零副作用和使用尾遞歸。如果你想,說其餘的項目,你可以簡單地從'iter'返回一個值。 – Asti

1

通過remobing已經處理過的,你不打算做什麼更快的元素。所有過濾器操作的成本平均會減半,但在每次迭代中構建新列表都會花費一些CPU週期,因此它不會顯着更快(從大的意義上講)。相反,您可以基於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>