Reputation: 41
I have an array of objects such as
const myArrayOfColors = [
{ color: "red", number: 123 },
{ color: "red", number: 12 },
{ color: "green", number: 6 },
{ color: "blue", number: 7 },
{ color: "purple", number: 54 },
{ color: "green", number: 74 },
{ color: "blue", number: 41 },
{ color: "purple", number: 74 },
];
and I have an array of strings that I have to use as an order reference:
myOrder = ["red", "blue", "purple", "green"];
so I have to sort my objects array in order to comply with my order reference. I should have an output like this:
const myArrayOfColors = [
{ color: "red", number: 123 },
{ color: "blue", number: 7 },
{ color: "purple", number: 54 },
{ color: "green", number: 6 },
{ color: "red", number: 12 },
{ color: "blue", number: 41 },
{ color: "purple", number: 74 },
{ color: "green", number: 74 },
];
Upvotes: 1
Views: 98
Reputation: 973
First build separate lists of the entries for each color, then use a custom comparator function for Array.prototype.sort().
const myArrayOfColors = [
{ color: "red", number: 123 },
{ color: "red", number: 12 },
{ color: "green", number: 6 },
{ color: "blue", number: 7 },
{ color: "purple", number: 54 },
{ color: "green", number: 74 },
{ color: "blue", number: 41 },
{ color: "purple", number: 74 },
];
myOrder = ["red", "blue", "purple", "green"];
myArraysPerColor = {};
for(const color of myOrder) {
myArraysPerColor[color] = myArrayOfColors.filter(v=>v.color===color);
}
myArrayOfColors.sort((a,b) =>
myArraysPerColor[a.color].indexOf(a)-myArraysPerColor[b.color].indexOf(b) ||
myOrder.indexOf(a.color)-myOrder.indexOf(b.color)
);
console.log(myArrayOfColors);
Upvotes: 0
Reputation: 5853
Will work even for uneven groups that cannot be repeated.
I've added {color:'green',number:74}
and {color:'red',number:74}
to the end of myArrayOfColors
:
const myArrayOfColors=[{color:'red',number:123},{color:'red',number:12},{color:'green',number:6},{color:'blue',number:7},{color:'purple',number:54},{color:'green',number:74},{color:'blue',number:41},{color:'purple',number:74},{color:'green',number:74}, {color:'red',number:74}]
const myOrder = ['red', 'blue', 'purple', 'green']
const res = []
let maxIterations = myArrayOfColors.length - myOrder.length
while (maxIterations--) {
myOrder.forEach(e => {
const c = myArrayOfColors.find(x => x.color === e) ?? {}
c.color && res.push({...c})
c.color = "-"
})
}
console.log(res)
.as-console-wrapper { max-height: 100% !important; top: 0; }
Upvotes: 0
Reputation: 25408
dict
that contains the color
and its number
in the respective array.max
number of elements in respective color
.max
and get color
and its number from dict
and store in the result
array.`const myArrayOfColors = [
{ color: "red", number: 123 },
{ color: "red", number: 12 },
{ color: "green", number: 6 },
{ color: "blue", number: 7 },
{ color: "purple", number: 54 },
{ color: "green", number: 74 },
{ color: "blue", number: 41 },
{ color: "purple", number: 74 },
{ color: "purple", number: 94 },
];
const myOrder = ["red", "blue", "purple", "green"];
let max = 0;
const dict = myArrayOfColors.reduce((acc, curr) => {
const { color, number } = curr;
if (acc[color]) acc[color].push(number);
else acc[color] = [number];
max = Math.max(max, acc[color].length);
return acc;
}, {});
const result = [];
for (let i = 0; i < max; ++i) {
myOrder.forEach((orderKey) => {
const { [i]: val } = dict[orderKey];
if (val) result.push({ color: orderKey, number: val });
});
}
console.log(result);
color
repeat more than in myArrayOfColors
, e.g purple
repeat more than any color in arrayconst myArrayOfColors = [
{ color: "red", number: 123 },
{ color: "red", number: 12 },
{ color: "green", number: 6 },
{ color: "blue", number: 7 },
{ color: "purple", number: 54 },
{ color: "green", number: 74 },
{ color: "blue", number: 41 },
{ color: "purple", number: 74 },
{ color: "purple", number: 94 },
{ color: "purple", number: 84 },
{ color: "purple", number: 64 },
{ color: "purple", number: 54 },
];
Upvotes: 0
Reputation: 4470
Not sure this is best way, You can try this. So basically we run through the myArrayOfColors
and then loop the order
to find the order element, push it in result, then after Delete the item from main source (myArrayOfColors)
. Of course think about Time Complexity (assuming n³)
here. (It's big 😶)
const myArrayOfColors = [
{color: 'red', number: 123},
{color: 'red', number: 12},
{color:'green', number: 6},
{color: 'blue', number: 7},
{color:'purple', number:54},
{color: 'green', number: 74},
{color:'blue', number:41},
{color: 'purple', number: 74},
]
const order = ['red', 'blue', 'purple', 'green']
const result = []
while(myArrayOfColors.length) {
for (const o of order) {
const colorIndex = myArrayOfColors.findIndex(e => e.color === o)
if (colorIndex > -1) {
result.push(myArrayOfColors[colorIndex])
myArrayOfColors.splice(colorIndex, 1)
}
}
}
console.log(result)
Upvotes: 1
Reputation: 13129
Here's a simple way to make groups of unique elements, sorted according to a colors array:
function* createdOrderedGroups(items, colors) {
items = [...items]
let colorIndex = 0;
while (items.length) {
const index = items.findIndex(item => item.color === colors[colorIndex])
if (index === -1) {
throw new Error('Each color did not have the same number of assosiated items.');
}
yield items[index]
items.splice(index, 1);
colorIndex = (colorIndex + 1) % colors.length
}
}
const myArrayOfColors = [
{color: 'red', number: 123},
{color: 'red', number: 12},
{color:'green', number: 6},
{color: 'blue', number: 7},
{color:'purple', number:54},
{color: 'green', number: 74},
{color:'blue', number:41},
{color: 'purple', number: 74},
]
console.log([...createdOrderedGroups(myArrayOfColors, ['red', 'blue', 'purple', 'green'])])
Basically, we gradually remove items from the input array every time we find one with the color we're looking for, until there are no items left. We know which color we're looking for, by using a colorIndex
variable, which starts at 0, and increments with each iteration until we get to the length of the color array, then it restarts at 0.
I'm using a generator here (the function* and yield stuff), but if that's new to you, you can instead just build a results array and return that whole array.
This solution will yield the first occurrence of each color from the input array, then it will yield the next occurrence it finds, and so forth, so the last item that has a color "red" will be one of the last elements yielded.
Upvotes: 0