Add `reduce` iterables utility

This commit is contained in:
Evan Hahn 2021-06-28 16:46:33 -05:00 committed by GitHub
parent 7cf7b1fca5
commit 4495a1ac67
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 33 additions and 2 deletions

View File

@ -1,7 +1,7 @@
// Copyright 2020-2021 Signal Messenger, LLC
// SPDX-License-Identifier: AGPL-3.0-only
import { debounce, reduce, uniq, without } from 'lodash';
import { debounce, uniq, without } from 'lodash';
import PQueue from 'p-queue';
import dataInterface from './sql/Client';
@ -13,6 +13,7 @@ import { SendOptionsType, CallbackResultType } from './textsecure/SendMessage';
import { ConversationModel } from './models/conversations';
import { maybeDeriveGroupV2Id } from './groups';
import { assert } from './util/assert';
import { map, reduce } from './util/iterables';
import { isGroupV1, isGroupV2 } from './util/whatTypeOfConversation';
import { deprecated } from './util/deprecated';
import { getSendOptions } from './util/getSendOptions';
@ -103,7 +104,7 @@ export function start(): void {
};
const newUnreadCount = reduce(
this.map((m: ConversationModel) =>
map(this, (m: ConversationModel) =>
canCount(m) ? getUnreadCount(m) : 0
),
(item: number, memo: number) => (item || 0) + memo,

View File

@ -11,6 +11,7 @@ import {
groupBy,
isIterable,
map,
reduce,
size,
take,
} from '../../util/iterables';
@ -311,6 +312,23 @@ describe('iterable utilities', () => {
});
});
describe('reduce', () => {
it('returns the accumulator when passed an empty iterable', () => {
const fn = sinon.fake();
assert.strictEqual(reduce([], fn, 123), 123);
sinon.assert.notCalled(fn);
});
it('iterates over the iterable, ultimately returning a result', () => {
assert.strictEqual(
reduce(new Set([1, 2, 3, 4]), (result, n) => result + n, 89),
99
);
});
});
describe('take', () => {
it('returns the first n elements from an iterable', () => {
const everyNumber = {

View File

@ -155,6 +155,18 @@ class MapIterator<T, ResultT> implements Iterator<ResultT> {
}
}
export function reduce<T, TResult>(
iterable: Iterable<T>,
fn: (result: TResult, value: T) => TResult,
accumulator: TResult
): TResult {
let result = accumulator;
for (const value of iterable) {
result = fn(result, value);
}
return result;
}
export function take<T>(iterable: Iterable<T>, amount: number): Iterable<T> {
return new TakeIterable(iterable, amount);
}