简体   繁体   中英

Efficient way to sort an array by one key, but list the array by another key?

I have an array that is structured like this:

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

I would like to display the contents of the array to the user (mapping each item to a div), sorted by count, and then alphabetically, such that the the above array should always maintain the following sorted order and be displayed like this:

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

So, that's easy enough. Just sort call something like:

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

The issue is that I also need the ability to determine if a given string is in the collection. For example, I would need to test if Carrot exists in the collection.

Normally I would use some sort of array filter function, but the arrays are very large (many tens of thousands of elements), and the naive solution is too slow. Also, there are several of these types of collections, and if possible I would like to avoid having to maintain multiple collections that I would have to manually keep in sync with one another.

Is there a way to elegantly solve this?

If you need to find a specific name in a big array, and you have performance issues, why don't you use the name as the key in a dedicated object like this:

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

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM