Итерационные проблемы с вложенным циклом for - PullRequest
0 голосов
/ 26 июня 2018

У меня проблема с циклом просмотра массива точечных объектов, сравнением каждого объекта с другими объектами и переносом его в подмассив. Основная проблема заключается в итерации с использованием цикла for. Во-первых, у меня есть набор очков:

 var points = [
   { id: 1, x: 0.0, y: 0.0 },
   { id: 2, x: 10.1, y: -10.1 },
   { id: 3, x: -12.2, y: 12.2 },
   { id: 4, x: 38.3, y: 38.3 },
   { id: 5, x: 79.0, y: 179.0 }
 ];

Затем я хочу сравнить каждую точку со ВСЕМИ другими точками. По-видимому, мой метод просто сравнивает i с j, который следующий в строке в массиве. То, что я хочу, это подмассив для каждого точечного объекта, который имеет идентификатор объекта, идентификатор точечного объекта, с которым он сравнивается, и расстояние между этими двумя точками. Ex output: [{1, 2, 12.74423}, {1, 2, 10.76233), {1, 3, 43.23323}, {1, 4, 23.45645}, {1, 5, 127.43432}]; Вот мой код, а ниже - вывод, который я получаю в своей консоли. Что я здесь не так делаю? Примечание: я вставил несколько случайных console.logs, чтобы посмотреть, что происходит.

   var pointPairs = [];
   for (let i = 0; i < points.length; i = i + 1) {
     var p1 = points[i];
     for (let j = i + 1; j < points.length; j = j + 1) {
       var p2 = points[j];
       var distance = Math.sqrt((p1.x - p2.x) ** 2 + (p1.y - p2.y) ** 2);
       pointPairs.push({ p1: p1.id, p2: p2.id, distance });
       console.log(pointPairs);
     };

   };

Результаты:

0:{p1: 1, p2: 2, distance: 14.28355697996826}
1:{p1: 1, p2: 3, distance: 17.253405460951758}
2:{p1: 1, p2: 4, distance: 54.16437943888954}
3:{p1: 1, p2: 5, distance: 195.65786465153911}
4:{p1: 2, p2: 3, distance: 31.536962440920014}
5:{p1: 2, p2: 4, distance: 56.01606912306503}
6:{p1: 2, p2: 5, distance: 201.26107422946941}
7:{p1: 3, p2: 4, distance: 56.84593213238745}
8:{p1: 3, p2: 5, distance: 190.10439237429526}
9:{p1: 4, p2: 5, distance: 146.46835835770128}

Ответы [ 2 ]

0 голосов
/ 26 июня 2018

Похоже, что ваш алгоритм работает, если цель состоит в том, чтобы провести одно сравнение между любыми двумя точками - т.е. если p1 и p2 считаются неупорядоченными - комбинация, а не перестановка.

Однако, если вы хотите, чтобы p1 и p2 содержали каждую возможную перестановку, а не только комбинацию, тогда начните j с 0 и пропустите итерацию, где i===j:

   var pointPairs = [];
   for (let i = 0; i < points.length; i = i + 1) {
     var p1 = points[i];
     innerLoop: for (let j = 0; j < points.length; j = j + 1) {
       if (j===i) continue innerLoop;
       var p2 = points[j];
       var distance = Math.sqrt((p1.x - p2.x) ** 2 + (p1.y - p2.y) ** 2);
       pointPairs.push({ p1: p1.id, p2: p2.id, distance });
       console.log(pointPairs);
     };

   };

(метка innerLoop не является строго необходимой, но помогает уточнить код при наличии вложенных циклов)

0 голосов
/ 26 июня 2018

Пойнт прав в том, что нужно начинать с нуля во втором цикле.

Если вам просто нужно перебрать список, я рекомендую избегать циклов for. Они многословны и подвержены ошибкам по сравнению со встроенным методом итерации массива (Array.forEach). Вот ваш код, конвертированный для использования Array.forEach. Я думаю, вы согласитесь, что это намного проще.

var points = [
   { id: 1, x: 0.0, y: 0.0 },
   { id: 2, x: 10.1, y: -10.1 },
   { id: 3, x: -12.2, y: 12.2 },
   { id: 4, x: 38.3, y: 38.3 },
   { id: 5, x: 79.0, y: 179.0 }
]
var pointPairs = [];
points.forEach((p1, i) => {
    points.forEach((p2, j) => {
        var distance = Math.sqrt((p1.x - p2.x) ** 2 + (p1.y - p2.y) ** 2);
        pointPairs.push({ p1: p1.id, p2: p2.id, distance });
        console.log(pointPairs);
    })
})
...