0

How do I achieve this without lodash chain function?

const results = chain(sortedItems || allItems)
            .filter((x) => this.filterItemsBySearchParam<T>(x, search))
            .filter((x) => this.filterItemsByFacets<T>(x, facets))
            .groupBy((x) => (groupBy ? [groupBy.split(',').map((path) => get(x, path))] : ''))
            .map((filteredItems: any, key) => {
                if (!isNaN(Number(limit))) {
                    filteredItems = [...filteredItems.slice(0, limit)];
                }

                return this.addData<T>(key, filteredItems.length, filteredItems);
            })
            .value();

I have tried using lodash flow, and some other ES6 functions, but none of them worked as expected. it could be that I'm not applying them correctly?

I have tried this:

const result = sortedItems || allItems
        .filter((x) => this.filterItemsBySearchParam<T>(x, search))
        .filter((x) => this.filterItemsByFacets<T>(x, facets))
        .groupBy((x) => (groupBy ? [groupBy.split(',').map((path) => get(x, path))] : ''))
        .map((filteredItems: any, key) => {
            if (!isNaN(Number(limit))) {
                filteredItems = [...filteredItems.slice(0, limit)];
            }

            return this.addData<T>(key, filteredItems.length, filteredItems);
        });

But the groupBy keeps throwing an error: groupBy is not a type of T.

I tried flow from here: Better and more performant than lodash chain, but like I said, I could not get it to work. Is there a way to achieve this? By the way, the .filter, .map, and .groupBy are all built-in ts functions.

user8107351
  • 367
  • 4
  • 20
  • 1
    Not sure if you know, perhaps it is why you are asking for an alternative, but using `_.chain` requires the *entire* lodash library IIRC – Dexygen Feb 04 '22 at 22:33
  • 1
    why? what's wrong with using the lodash method? – szaman Feb 04 '22 at 22:44
  • 1
    "_.groupBy [is a] built-in ts functions_" looks like it is not in current stable version 4.5.4 https://github.com/microsoft/TypeScript/issues/46811#issuecomment-995883968 – ghybs Feb 04 '22 at 23:14
  • @Dexygen, Yes, that is why I am asking for an alternative because _.chain is the ONLY lodash function I'm currently using, doesn't make sense to import the entire library just for that. – user8107351 Feb 05 '22 at 08:27
  • 1
    You'll just end up importing *alternative* code. For instance, I had a go at mimicking the Java Streams API in answer to [this question](https://stackoverflow.com/q/43408033/5459839) – trincot Feb 05 '22 at 09:25
  • 1
    Also: when you use `_.chain`, you're not only using that lodash function, but all the chained functions as well, as they are no longer the native array methods, but specific implementations that can work on a "chain" supporting *lazy* evaluation. Your alternative will be *greedy*. And the initial expression should at least have parentheses. – trincot Feb 05 '22 at 09:33
  • I'm using only _.chain here, the other functions are typescript native function. .filter, .map, and .groupBy are all in-built, not from lodash. – user8107351 Feb 05 '22 at 10:20

1 Answers1

0

Try this:

const filteredItems = (sortedItems || allItems || []).filter(x => this.filterItemsBySearchParam<T>(x, search) && this.filterItemsByFacets<T>(x, facets));
const results = Object.entries(groupBy ? filteredItems.reduce((map, x) => {
    const key = JSON.stringify((groupBy.match(/[^,]+/g) || []).map(path => get(x, path)));
    (map[key] || (map[key] = [])).push(x);
    return map;
}, {}) : {'': filteredItems}).map(([key, filteredItems]) => {
    if (+limit > 0) {
        filteredItems = filteredItems.slice(0, limit);
    }

    return this.addData<T>(key, filteredItems.length, filteredItems);
});

ask if you have any questions :)

vamp
  • 120
  • 1
  • 2