簡體   English   中英

從 typescript 中的對象列表中查找鍵的唯一值的高效方法

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

在此處輸入圖像描述

我正在開發一個 angular 應用程序,它有一個

  1. 一組過濾器
  2. 和表格中的記錄

表中的列對應於過濾器。 在任何時候,過濾器都包含來自相應列的唯一值作為選項。

對於一條記錄,一列可以包含多個值(即來自相應過濾器的多個選項)

當用戶從過濾器中選擇一個選項時,表中的記錄將被過濾,並且過濾后的結果(根據用戶的選擇)顯示給用戶。

導出過濾記錄集后,通過查找每列的唯一值,從過濾記錄集導出每個過濾器的唯一值。

過濾器對象的鍵對應於記錄對象的列我有一個記錄列表和一個過濾器列表。 我想遍歷這兩個列表並找到每個鍵的列的唯一值。

我正在使用以下邏輯從我的消息中查找過濾器的唯一選項。

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

下面的邏輯在我的代碼中花費的時間最多。 8k 條記錄大約需要 7 秒。

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

我無法讓我的代碼表現得更好。 請你能建議我哪里出錯了。

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

我認為您遇到的性能問題是Array.prototype.concat()不會修改現有數組,而是返回一個新數組。 不變性很好,但它似乎與您的用例無關:除了最后一個之外,您創建的每個uniqueList數組都將被丟棄。 Object 在 JavaScript 中的創建速度相當快,但創建數千個數組對象只是為了立即丟棄它們會減慢速度。

我的建議是將concat()替換為修改現有數組的內容,例如Array.prototype.push()

也就是說,你可以改變

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

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

當我運行一個創建 6000 行和 14 個過濾器的模擬時(請參閱下面的游樂場鏈接), concat()版本大約需要 7.5 秒,而push()版本大約需要 38 milliseconds 希望大約 200 的改進因素在您的環境中保持不變,並產生足夠的影響以滿足您的需求。

請注意,我沒有處理您的原始問題似乎具有的任何“唯一”或“功能”方面,因為您的可重現示例代碼也沒有涉及到這一點。 通過 object 鍵可能比數組更容易計算唯一字符串,甚至可能通過Set 但同樣,希望將concat()更改為push()對您來說就足夠了。

Playground 代碼鏈接

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM