简体   繁体   English

从 typescript 中的对象列表中查找键的唯一值的高效方法

[英]Performant way of finding unique values of keys from a list of objects in typescript

在此处输入图像描述

I am working on an angular app that has a我正在开发一个 angular 应用程序,它有一个

  1. a set of filters一组过滤器
  2. and records present in a table和表格中的记录

Columns in the table correspond to filters.表中的列对应于过滤器。 At any time filters contain unique values from corresponding columns as options.在任何时候,过滤器都包含来自相应列的唯一值作为选项。

For a record, a column can contain more than 1 values (ie more than 1 options from the corresponding filter)对于一条记录,一列可以包含多个值(即来自相应过滤器的多个选项)

When a user selects an option from a filter, the records in the table are filtered and the filtered results (as per user the selection) are shown to the user.当用户从过滤器中选择一个选项时,表中的记录将被过滤,并且过滤后的结果(根据用户的选择)显示给用户。

Once the set of filtered records is derived, unique values for each filter are derived from the set of filtered records by finding unique values for each column.导出过滤记录集后,通过查找每列的唯一值,从过滤记录集导出每个过滤器的唯一值。

Key of Filter objects correspond to columns of Record objects I have a list of records and a list of filters.过滤器对象的键对应于记录对象的列我有一个记录列表和一个过滤器列表。 I want to iterate over both these lists and find the unique value of columns for each key.我想遍历这两个列表并找到每个键的列的唯一值。

I am using the below logic to find unique options for filters from my messages.我正在使用以下逻辑从我的消息中查找过滤器的唯一选项。

export function filterOptionsService(records: Record[], filters: RecordFilter[]): RecordFilter[] {
    const newFilters: RecordFilter[] = filters.map(filter => {

        //logic to find all values for a column from the set of records 
        const filterOptions = records.reduce((uniqueList, record) => uniqueList.concat(record[filter.key]), []);

        //logic to find unique values for a column from the set of records
        //which act as options of corresponding filters.
        const uniqueOptions = uniqBy(filterOptions, (opt) => filter.valueFunction ? filter.valueFunction(opt) : opt);

        const filterOptions: FilterOption[] = uniqueOptions.map(value => {
            return {
                label: filter.labelFunction ? filter.labelFunction(value) : value,
                value: filter.valueFunction ? filter.valueFunction(value) : value,
            };
        });
        filter.options = orderBy(dropListOptions, 'label');

        //here is my logic to find the count of each option, present in the filtered records
        filter.options = filter.options.map(option => ({
            ...option,
            count: filter.valueFunction
                ? filterOptions.filter(value => filter.valueFunction(value) === option.value).length
                : filterOptions.filter(value => value === option.value).length
        }));
        return filter;
    });
    return newFilters;
}

interface Filter {
    key: string;
    labelFunction?: Function;
    valueFunction?: Function;
    order: number;
    multiple: boolean;
    options: DropListOption[];
    values: DropListOption[];
}


interface Record {
    column1: string;
    column2: string;
    column3: string | string[];
    .
    .
    columnN: string;
}

The below logic takes the most time in my code.下面的逻辑在我的代码中花费的时间最多。 It takes around 7 seconds for 8k records. 8k 条记录大约需要 7 秒。

const filterOptions = records.reduce((uniqueList, record) => 
                              uniqueList.concat(record[filter.key]), []); 

I am unable to make my code perform better.我无法让我的代码表现得更好。 Please can you suggest where am I going wrong.请你能建议我哪里出错了。

Here is sample code on typescrip playground https://www.typescriptlang.org/play?#code/FASwdgLgpgTgZgQwMZQAQDEQBtowPIAOEIA9mKgN7Co201YIBGUWAXKgM4QzgDmA3NTq0AbgiwBXKOwRgAnoOG1kxEVAD87RiRJYosxUtQEEcrCQQATTalkKhSpCQmQbYCQFtmMQzQC+-LTA1AD0IRwIHgR6qGJ6HKhwJDCoANZQcrYwaAQwJASwEHIAjAA0xnkFMEUATKigkLCIKKgASlBOMJaYOLCUDsLpcuxcPGAC9UaoDMxY6C5IxGQ282CLpGC+wnFSq+vL7HtLmwN0yZaw7O5esFt0HhI4INHSqNq6+idT+ccch9i4QjHADaAF07qJxFI-hgAbAgRswVsAkFgGEKvlqiAoAkSHA2h1zqgkAwOAkENlOJE0AgEkNUHiCZ1unCUiTaRw0SFUBAABYgBICzggKJYEBwbGWVDZKo4yAIY6oDyZFQScTE0kJXm0pV2JXJHKVQrYzngXDNNCtEgAd36dFy+UKJRG3D4SIGDqqtRdYwEwACwWATjAXFQ4BAxHEVutMOjYNQAF5UMDTlNhBRPU7iqxgQAiMhQXPlXN87KF0GlTPVOQ1Vi5phIXN+UqptO0DNG6vZvMStRF1C5sDgcuVzve3MXOBNlttqYdx1dnP5sCF4ulqCrge9zeD4e5itV8cNputtPg4JBMIASVsHgZYCwKrJIF4Q-GsShOJ5JDSGQxXsyJIUg4EVonFEAkAVDYgzIUNw0jOZWVjQkuh6XB4yTFNZyUCghjrQ8Sn7c5LjKJVHmIF5WEQLAOCgcofg2P4wXKHYcXYMFm1PNNcIyfCxxrIiukuGpygeJ5KOo2j6KIRicwrD9JDY5NQT8GguKMc9gglXp8Bk2CAGVYBECCoAACngkAoxtDhSgs8Q0NgDgAE Here is sample code on typescrip playground https://www.typescriptlang.org/play?#code/FASwdgLgpgTgZgQwMZQAQDEQBtowPIAOEIA9mKgN7Co201YIBGUWAXKgM4QzgDmA3NTq0AbgiwBXKOwRgAnoOG1kxEVAD87RiRJYosxUtQEEcrCQQATTalkKhSpCQmQbYCQFtmMQzQC+-LTA1AD0IRwIHgR6qGJ6HKhwJDCoANZQcrYwaAQwJASwEHIAjAA0xnkFMEUATKigkLCIKKgASlBOMJaYOLCUDsLpcuxcPGAC9UaoDMxY6C5IxGQ282CLpGC+wnFSq+vL7HtLmwN0yZaw7O5esFt0HhI4INHSqNq6+idT+ccch9i4QjHADaAF07qJxFI-hgAbAgRswVsAkFgGEKvlqiAoAkSHA2h1zqgkAwOAkENlOJE0AgEkNUHiCZ1unCUiTaRw0SFUBAABYgBICzggKJYEBwbGWVDZKo4yAIY6oDyZFQScTE0kJXm0pV2JXJHKVQrYzngXDNNCtEgAd36dFy+UKJRG3D4SIGDqqtRdYwEwACwWATjAXFQ4BAxHEVutMOjYNQAF5UMDTlNhBRPU7iqxgQAiMhQXPlXN87KF0GlTPVOQ1Vi5phIXN+UqptO0DNG6vZvMStRF1C5sDgcuVzve3MXOBNlttqYdx1dnP5sCF4ulqCrge9zeD4e5itV8cNputtPg4JBMIASVsHgZYCwKrJIF4Q-GsShOJ5JDSGQxXsyJIUg4EVonFEAkAVDYgzIUNw0jOZWVjQkuh6XB4yTFNZyUCghjrQ8Sn7c5LjKJVHmIF5WEQLAOCgcofg2P4wXKHYcXYMFm1PNNcIyfCxxrIiukuGpygeJ5KOo2j6KIRicwrD9JDY5NQT8GguKMc9gglXp8Bk2CAGVYBECCoAACngkAoxtDhSgs8Q0NgDgAE pBGCdEb21NRUGKAAWRJWQZRgACsOggTl0WtXkoHIDyEC8gAOVJpRtQKQsWBI+TQWYUuySwJBaTEICgsgeQQdIEgANgAWgAdk4QkwEsDgADpgDgBZFW0wE9JDQyYGMlBTLyGN2DjeSusc0aUJZHSwSc-pTgmmAWo8BACFMpbEwAPjtIwwnMXgIO-fzGtsLAsAU6FEmSWxiV0TxyDgPI70y+qIAZfFsmZBJT2DUMloRWDE2SmNmty-KzNMlwQAARykAAZAUIHKYb5oTHbUGhuGoERrhmuDSCICGm1gSW5qhlBJzyjmwIuN+2CPmag7TIAcgBnqOBZ0p2d+FzsNbPwXP9QMgA pBGCdEb21NRUGKAAWRJWQZRgACsOggTl0WtXkoHIDyEC8gAOVJpRtQKQsWBI+TQWYUuySwJBaTEICgsgeQQdIEgANgAWgAdk4QkwEsDgADpgDgBZFW0wE9JDQyYGMlBTLyGN2DjeSusc0aUJZHSwSc-pTgmmAWo8BACFMpbEwAPjtIwwnMXgIO-fzGtsLAsAU6FEmSWxiV0TxyDgPI70y+qIAZfFsmZBJT2DUMloRWDE2SmNmty-KzNMlwQAARykAAZAUIHKYb5oTHbUGhuGoERrhmuDSCICGm1gSW5qhlBJzyjmwIuN+2CPmag7TIAcgBnqOBZ0p2d+FzsNbPwXP9QMgA

I think the performance problem you're having is that Array.prototype.concat() does not modify an existing array, but instead returns a new array.我认为您遇到的性能问题是Array.prototype.concat()不会修改现有数组,而是返回一个新数组。 Immutability is nice, but it doesn't seem relevant to your use case: every uniqueList array you create except for the very last one will be discarded.不变性很好,但它似乎与您的用例无关:除了最后一个之外,您创建的每个uniqueList数组都将被丢弃。 Object creation is fairly fast in JavaScript, but creating thousands of array objects only to immediately throw them away is slowing things down. Object 在 JavaScript 中的创建速度相当快,但创建数千个数组对象只是为了立即丢弃它们会减慢速度。

My suggestion would be to replace concat() with something that modifies the existing array, such as Array.prototype.push() :我的建议是将concat()替换为修改现有数组的内容,例如Array.prototype.push()

That is, you could change也就是说,你可以改变

const filterOptions = rows.reduce(
  (uniqueList, row) => uniqueList.concat(row[filter.key]), []
);

to

const filterOptions: string[] = [];
for (let row of rows) filterOptions.push(...row[filter.key]);

When I run a simulation where I create 6000 rows and 14 filters (see playground link below), the concat() version takes about 7.5 seconds, whereas the push() version takes about 38 milliseconds .当我运行一个创建 6000 行和 14 个过滤器的模拟时(请参阅下面的游乐场链接), concat()版本大约需要 7.5 秒,而push()版本大约需要 38 milliseconds Hopefully that factor of ~200 improvement holds in your environment and makes enough of an impact to be sufficient for your needs.希望大约 200 的改进因素在您的环境中保持不变,并产生足够的影响以满足您的需求。

Note that I'm not dealing with any "uniquifying" or "function" aspects that your original problem seems to have, since your reproducible example code doesn't touch that either.请注意,我没有处理您的原始问题似乎具有的任何“唯一”或“功能”方面,因为您的可重现示例代码也没有涉及到这一点。 Unique strings might be more easily tallied via an object key than an array, or maybe even via a Set .通过 object 键可能比数组更容易计算唯一字符串,甚至可能通过Set But again, hopefully changing concat() to push() will be enough for you.但同样,希望将concat()更改为push()对您来说就足够了。

Playground link to code Playground 代码链接

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 从基于两个键的对象的两个数组中查找唯一值,即在JavaScript中从and到 - finding unique values from two arrays of objects based on two keys i.e from and to in javascript 用唯一键将对象数组转换为对象的最有效方法是什么 - What is the most performant way to convert an Array of Object to an Object with unique keys 如何从对象数组中获取具有特定键的唯一值的对象? - How to get objects with unique values for specific keys from array of objects? 如何从对象列表中获取唯一值? - how to get unique values from a list of objects? 根据两个键从对象数组中获取唯一值 - Get unique values from an array of objects based on two keys Javascript:对象数组到包含值数组的对象-最有效的方式? - Javascript: Array of objects to object containing arrays of values - most performant way? 通过动态查找键来修改 object 值 TypeScript - Modify object values by finding keys dynamically TypeScript 从对象返回唯一键列表的正确方法 - Correct way to return a list of unique keys from Object 如何使用 javascript 从对象数组中执行添加相同键的对象值并返回唯一对象? - How to perform addition of same keys' values of objects and return unique objects from array of objects using javascript? 显示 angular typescript 中 object 列表中的键和值 - Displaying keys and values from a list of object in angular typescript
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM