简体   繁体   中英

Iterating over every pair of elements in a Map

I have a Map which holds Shape object values with their id as key. I need to iterate over every pair of Shapes in this Map, but I want to iterate over each pair only once.

I know I can use forEach or for..of, but I can't find a way to prevent duplicate pairs. Also, this should be a as efficient as possible.

shapes.forEach((shape1, shapeId1) => {
    shapes.forEach((shape2, shapeId2) => {
        // iterating over each pair many times
    });
});

I'd suggest first converting the Map to an array of its entries:

const entryArray = Array.from(shapes.entries());

Then you can choose to iterate pairs either via traditional for loop:

console.log("FOR LOOP");
for (let i = 0; i < entryArray.length; i++) {
  const [shapeId1, shape1] = entryArray[i];
  for (let j = i + 1; j < entryArray.length; j++) {
    const [shapeId2, shape2] = entryArray[j];
    console.log(shapeId1, shapeId2);
  }
}

Or via the functional forEach array methods:

console.log("FOREACH");
entryArray.forEach(([shapeId1, shape1], i) =>
  entryArray.slice(i + 1).forEach(([shapeId2, shape2]) => {
    console.log(shapeId1, shapeId2);
  })
);

In each case you are avoiding duplicates by the inner loop only iterating the elements after the outer loop index. I don't know what your Shape or id types look like, but given this:

interface Shape {
  area: number;
}

const shapes: Map<string, Shape> = new Map([
  ["a", { area: 1 }],
  ["b", { area: 2 }],
  ["c", { area: 3 }]
]);

The above code outputs

FOR LOOP
a b
a c
b c
FOREACH
a b
a c
b c

So you can see that you get distinct pairs. Hope that helps; good luck!

Link to code

Use a Set with the two indexes:

let indexes = new Set();

shapes.forEach((shape1, shapeId1) => {

    shapes.forEach((shape2, shapeId2) => {

        if (set.has(`${shapeId1}-${shapeId2}`) || set.has(`${shapeId2}-${shapeId1}`)) return;
        set.add(`${shapeId1}-${shapeId2}`);

    });

});

You can use two for iterations using an index and start the nested iteration from the root index + 1. This will ensure you that you will never process two pairs.

const arr = [1,2,3,4];


for (let i = 0; i<arr.length-1; i++) {
  for (let j = i+1; j<arr.length; j++) {
    console.log(`${arr[i]} - ${arr[j]}`)
  }
}

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