Что может быть более эффективным с точки зрения машин, чем комбинирование loop + lodash? - PullRequest
0 голосов
/ 23 октября 2019

Обновление: отредактировал код для более ясного объяснения.

Мне нужно найти x номер объекта в массиве по отношению к другому массиву свойств, я буду использовать цикл for + lodash.filter для получения списка,Мне было интересно, как это может быть более эффективным для NodeJs, поскольку NodeJs является однопоточным. Примером использования является уменьшение количества вызовов MySQL. Например, у меня есть список продуктов, и я хочу получить подмножество через их категорию продуктов. Итак, я получу что-то вроде этого:

const lodash = require('lodash');
...
let productCategories = [{id:111,...},{id:222,...},{id:333,...},{id:444,...}];
let products = await this.getProductByProductCategories(lodash.map(productCategories,'id')); //Does mysql call whereIn ... which I will not include here.

for(let productCategory of productCategories){
    let productSubset = lodash.filter(products, {product_category_id: productCategory.id};
     //Do something with productSubset
     //I also want to reference the parent object here: productCategory.xxx
}

Есть ли более эффективный (и дружественный к коду) способ сделать комбо for loop + lodash.filter?

Ответы [ 4 ]

1 голос
/ 23 октября 2019

Нет необходимости делать фильтр внутри для цикла. Вам нужно использовать _. GroupBy .

Например

...
const productSubsets = _.groupBy(products, 'product_category_id');
for (let key in productSubsets) {
  // do something with productSubsets[key]
}
0 голосов
/ 23 октября 2019

Зависит от того, как именно вы хотите использовать подмножество, но вы можете рассмотреть возможность возврата упорядоченного набора продуктов из БД

function doSomethingWithProductSubset(productSubset) {
    // do something with product subset
    console.dir(productSubset);
}
const productCategoryIds = [111,222,333,444,555];
const products = await getProductByProductCategoriesOrderedByCategory(productCategoryIds);
if (products && products.length) {
    let productSubset = [];
    let category = products[0].category;
    products.forEach(product => {
        if (productSubset.length && product.category != category) {
            doSomethingWithProductSubset(productSubset);
            productSubset = [];
            category = product.category;
        }
        productSubset.push(product);
    });
    if (productSubset.length) doSomethingWithProductSubset(productSubset);
}
0 голосов
/ 23 октября 2019

Если вы хотите придерживаться lodash, вы можете использовать _.groupBy, а затем сделать что-то со значениями произведенного объекта:

const productsByCategoryId = _.groupBy(products, 'product_category_id');

Вы можете получить значения (например, с помощью lodash's _.values ​​()) или mapэто с помощью _.mapValues ​​() или просто используйте простой javascript для доступа к нужным вам данным.

Это более элегантно, но, вероятно, не очень быстро. Если вы хотите быть более эффективным в асинхронной среде, возможно, вам следует попробовать реагировать как:

from(products)
  .pipe(
    groupBy(product => product.product_category_id),
    //do something in pipe 
  )

Дополнительная информация: https://www.learnrxjs.io/operators/transformation/groupby.html

0 голосов
/ 23 октября 2019

Не уверен, что lodash делает под капотом, но вложенный цикл for, как это обычно занимает O(n^2) время;однако, используя хеш-карты, вы можете сократить это время до O(n), например,

const productCategoryIds = [111,222,333,444,555];
const mappedProductCategoryIds = productCategoryIds.reduce((obj, id) => {
    obj[id] = true;
    return obj;
}, {});

const products = await this.getProductByProductCategories(productCategoryIds); //Does mysql call whereIn ... which I will not include here.

const productSubset = products.filter(product => mappedProductCategoryIds[product.product_category_id]);

//Do something with productSubset

Сначала мы проведем итерацию по productCategoryIds и создадим хеш-карту (mappedProductCategoryIds), по которой мы можем проверитьproduct_category_id любого product, просто проверяя, является ли значение ключа product_category_id в этой хэш-карте mappedProductCategoryIds равным truthy (т. е. true) или falsey (т. е. undefined). (Поиск по хеш-карте занимает O(1) раз.)

JavaScript filter() соберет product, если mappedProductCategoryIds содержит его product_category_id;в противном случае он отклонит его.

...