2016-11-22 43 views
8

Mam dwie pętle, po jednej na każdy dzień miesiąca, inne ze wszystkimi wydarzeniami w tym miesiącu. Załóżmy, że mam 100 000 wydarzeń. Poszukuję sposobu usunięcia zdarzeń z głównych wydarzeń List po ich "skonsumowaniu".immutable.js filtruj i mutuj (usuń) znaleziono wpisy

Kod jest coś takiego:

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}]) 
} 

Z lodash może po prostu zrobić coś takiego:

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) 
} 

Jak osiągnąć ten sam optymalizacji z immutablejs? Naprawdę nie oczekuję rozwiązania dla mojego sposobu na iterację listy, ale na sprytny sposób zmniejszenia liczby zdarzeń List w taki sposób, że staje się coraz mniejszy ..

Odpowiedz

4

Możesz wypróbować Map z wydarzeniami podzielonymi na kosze - na podstawie twojego przykładu, bin na podstawie dat - możesz odszukać bin, przetworzyć go jako wsad i usunąć O (1). Niezmienne mapy są dość tanie i znacznie lepsze niż przeglądanie list. Możesz ponieść koszt jednorazowego binningu, ale zamortyzuj go przez O (1).

Coś takiego może:

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

Przy okazji należy dodać, podejście to czysta funkcjonalny zero efektów ubocznych, i za pomocą ogona rekursji. Jeśli chcesz, powiedz resztę pozycji, możesz po prostu zwrócić wartość z 'iter'. – Asti

1

Przez remobing już przetworzone elementy, które nie są zamiar zrobić coś szybciej. Koszt wszystkich operacji filtrowania będzie średnio o połowę mniejszy, ale skonstruowanie nowej listy w każdej iteracji będzie kosztować kilka cykli procesora, więc nie będzie to znacznie szybsze (w dużym sensie O). Zamiast tego możesz zbudować indeks, na przykład niezmienną mapę, opartą na initialDate -s, dzięki czemu wszystkie wywołania filter będą niepotrzebne.

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>