【问题标题】:Efficient way to sort an array by one key, but list the array by another key?按一个键对数组进行排序但按另一个键列出数组的有效方法?
【发布时间】:2020-03-01 21:31:06
【问题描述】:

我有一个结构如下的数组:

[{ name: "Aardvark", count: 9 }, 
 { name: "Apple", count: 12 }, 
 { name: "Banana", count: 4 }, 
 { name: "Carrot", count: 6 }]

我想向用户显示数组的内容(将每个项目映射到一个 div),按计数排序,然后按字母顺序排列,这样上述数组应始终保持以下排序顺序并显示为这个:

[{ name: "Apple", count: 12 }, 
 { name: "Aardvark", count: 9 },  
 { name: "Carrot", count: 6 },
 { name: "Banana", count: 4 }]

所以,这很容易。只需排序调用类似:

arr.sort((a, b) => b.count - a.count || a.name.toLowerCase().localeCompare(b.name.toLowerCase()));

问题是我需要能够确定给定字符串是否在集合中。例如,我需要测试集合中是否存在Carrot

通常我会使用某种数组过滤功能,但数组非常大(数万个元素),而且天真的解决方案太慢了。此外,这些集合有多种类型,如果可能的话,我希望避免维护多个集合,我必须手动保持彼此同步。

有没有办法优雅地解决这个问题?

【问题讨论】:

  • 如果找到你想做什么?
  • @NinaScholz 我想测试一组项目是否存在。如果在较大的集合中找到它们中的任何一个,当我将它们映射到一个 div 时,我会将它们设为红色而不是灰色(哈哈)。
  • 它不是数据表示的一部分吗?不是排序的一部分?
  • 不确定你的意思。我想理想情况下它以某种方式排序,以便将项目列表渲染到 DOM 足够快,因为它目前是 O(nk)
  • @RyanPeschel 你不能用名字作为关键字的字典吗?

标签: javascript arrays node.js performance


【解决方案1】:

如果您需要在大数组中查找特定名称,并且遇到性能问题,为什么不使用该名称作为专用对象中的键,如下所示:

const arr = [{ name: "Apple", count: 12 }, 
 { name: "Aardvark", count: 9 },  
 { name: "Carrot", count: 6 },
 { name: "Banana", count: 4 }];

// Initialize the object using the name as the key

const res = arr.reduce((accumulator, currentValue) => {
        (accumulator[currentValue.name] || (accumulator[currentValue.name] = [])).push(currentValue);
        return accumulator;
    }, {});

// Keep the object in sync

const handler = {
    set: function(target, property, value) {
        if(!isNaN(property)) {
            if(res[value.name]) {
                const index = res[value.name].indexOf(target[property]);
                if(index > -1) {
                    res[value.name].splice(index, 1, value);
                } else {
                    res[value.name].push(value);
                }
                
            } else {
                res[value.name] = [value];
            }

        } 

        target[property] = value;
        return true;
    }
};

const proxy = new Proxy(arr, handler);

// Use the proxy instead of the array in your whole application

proxy.push({
    name: "Mango",
    count: 13
});

console.log(proxy);
console.log(res.Mango);

proxy[0] = { name: "Apple", count: 13 };

console.log(proxy);
console.log(res.Apple);

proxy.push({ name: "Apple", count: 14 });

console.log(proxy);
console.log(res.Apple);

【讨论】:

  • 我在 OP 中提到了这一点。必须维护一个单独的对象并手动保持它与数组同步是非常容易出错的。如果可能的话,我非常想避免它,因为数组在整个代码库的许多地方都发生了变化(并且有多个)。它已经够复杂了。
猜你喜欢
  • 2011-02-10
  • 2020-03-19
  • 2017-04-02
  • 2016-06-28
  • 1970-01-01
  • 2012-09-02
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多