重构复杂的嵌套数组

Restructure complex nested array

提问人:Jonas0000 提问时间:12/2/2017 最后编辑:Jonas0000 更新时间:12/2/2017 访问量:201

问:

我有一个这样的数组:

var my_array= [
    [2, [[9, 10]]],
    [5, [[10, 11]]],
    [4, [[11, 9]]],
    [1, [[19, 2], [41, 10]]],
    [7, [[17, 3]]],
    [0, [[11, 4], [18, 5]]]
]

中的数组包括另外两个数组(第一个不是必需的,但查看第二个数组 ( :此数组包含不同的 x/y 坐标my_arraymyarray[1][18, 4])

我想得到另一个看起来像这样的数组作为结果(解释如下):

var result_array= [
    [ [2, [9, 10]], [5, [10, 11]], [4, [11, 9]], [0, [11, 4]] ],
    [ [1, [19, 2]],  [0, [18, 5]] , [7, [17, 3]] ],    
    [ [1, [41, 10]] ]
]

数组现在按其 x 值 ( --> x-value: ) 排序,并分组到新数组中。例如,x 值之间的差异可以是 +/- 2 个索引(x 值 7,8,9,10,11)可以位于一个组中。[9, 10]9

我不知道如何编码;这是我到目前为止所拥有的:

var my_array= [
        [2, [[9, 10]]],
        [5, [[10, 11]]],
        [4, [[11, 9]]],
        [1, [[19, 2], [41, 10]]],
        [7, [[17, 3]]],
        [0, [[11, 4], [18, 5]]]
    ]

function sortArray(array) {
  var difference = 2,
    result = '';

  var array_sorted = [];
    array.forEach(function(a) {
     a[1].forEach(function(b) {
       array_sorted.push([b[0],b[1],a[0]]);
    })
  })
  array_sorted = array_sorted.sort(function(a,b) {return a[0]-b[0]});
  
  array_sorted.forEach(function(a) {
    if (a[0] > difference) {
    difference = a[0];
     array_sorted.push(array_group); array_group = [];}
     array_group.push([a]);
  })

  return array_sorted;
}

console.log(sortArray(my_array));


编辑:我忘了提到的一点是,应该分组的坐标不应大于 .请看下面的例子:y-value difference1

(x: 3, y:1),(x: 1, y:2),(x: 2, y:3),(x: 4, y:4) --> not (x: 4, y:41)

编辑 2

var my_array= [
    [2, [[9, 10]]],
    [5, [[10, 11]]],
    [4, [[11, 9]]],
    [1, [[19, 2], [41, 10]]],   
    [7, [[17, 3]]],
    [0, [[11, 4], [18, 5]]]
]

var result_array= [
    [ [2, [9, 10]], [5, [10, 11]], [4, [11, 9]] ], // line 1
    [ [0, [11, 4]] ],                              // line 2 
    [ [1, [19, 2]] ],                              // line 3
    [ [7, [17, 3]] ],                              // line 4 
    [ [0, [18, 5]] ],                              // line 5 
    [ [1, [41, 10]] ]                              // line 6 
]

如果你看一下第 1 行、第 2 行和第 2 行:x 值(第 2 行:“11”和第 1 行:“9”、“10”、“9”将完美匹配在一起。现在,我还想分离 y 值,就像我在上面编辑的示例中一样。 --> 即使 ,如果有,它们也应该被分组到新的数组中。x-values match togethery-values match together

Y 值匹配意味着,存在类似于行 --> (x: 2, y:4),(x: 1, y:5), (x: 2, y:6), (x: 2, y:7) 而不是像
(x: 4, y:42) 这样的值
)

我希望我的编辑能更容易理解我的想法。

提前致谢,乔纳斯

JavaScript jQuery 多维数组

评论

0赞 Jonas0000 12/2/2017
...真的不知道该怎么回答这样的评论@mplungjan
0赞 mplungjan 12/2/2017
你做了一个片段。我认为,该片段立即显示了一个错误,您需要在继续之前解决该错误return b[1][0] - b[1][0]
0赞 Daniel Beck 12/2/2017
“假设说,x 值之间的差异可以是 +/- 2 个索引”我认为这不是一个足够清晰的规范,无法编码。如果您有 x 个值 1、2、3、4、5、6、7、9 和 10,将如何分组?
0赞 Jonas0000 12/2/2017
@DanielBeck 从第一个数组开始,每次(第一个数组 --> xValue: 9)[2, [[9, 10]]]
0赞 Daniel Beck 12/2/2017
“每次从第一次开始”,嗯,这就是我的观点;例如,假设您的数据包含 x 个值 1...10,如果您从第一个值开始,这将导致 (1,2,3) 被组合在一起,即 1 +/-2;然后(4,5,6);(7,8,9);(10). 但是,如果你的目标是最小数量的组,你会想要 (1..5), (6..10) -- 这编码起来会更复杂,因为它需要查看整个 x 值集来确定如何最好地对它们进行分组,而不仅仅是从第一个值开始......

答:

0赞 mpasko256 12/2/2017 #1

编辑:格式和代码样式

编辑 2:对原始问题编辑的回应

var my_array= [
  [2, [[9, 10]]],
  [5, [[10, 11]]],
  [4, [[11, 9]]],
  [1, [[19, 2], [41, 10]]],   
  [7, [[17, 3]]],
  [0, [[11, 4], [18, 5]]]
]

    var xdifference = 2;
    var ydifference = 1;

  function split(input_array) {
    var splitted = [];

    input_array.forEach(function (item) {
      var coordinates = item[1];
      coordinates.forEach(function (coordinate) {
        splitted.push([item[0], coordinate]);
      });
    });
    return splitted;
  }

  function getXValueOf(item) {
    return item[1][0];
  }

  function getYValueOf(item) {
    return item[1][1];
  }

  function divideIntoHeaps(sorted_array) {
    var heaps = [];
    function findMatchingHeap(item) {
       var matching = heaps.find(function (heap) {
         return heap.every(function (itemOfHeap) {
           var xMatches = Math.abs(getXValueOf(item) - getXValueOf(itemOfHeap)) <= xdifference+1;
           var yMatches = Math.abs(getYValueOf(item) - getYValueOf(itemOfHeap)) <= ydifference+1;
           return xMatches && yMatches;
         });
       });
       return matching;
    }
    function allocate(item) {
      if (heaps.length == 0) {
        heaps.push([item]);
      } else {
        var matchingHeap = findMatchingHeap(item);
        if (matchingHeap !== undefined) {
          matchingHeap.push(item);
        } else {
          heaps.push([item]);
        }
      }
    }
    sorted_array.forEach(allocate);
    return heaps;
  }

  function sortArray(my_array) {
    var splitted = split(my_array);
    var result = divideIntoHeaps(splitted);
    return result;
  }
  
  var result = sortArray(my_array);
  result.forEach( function (row) {
     console.log(JSON.stringify(row));
  });
.as-console-wrapper { max-height: 100% !important; top: 0; }

评论

1赞 Jonas0000 12/2/2017
好吧,很长一段时间都试图得到你的解决方案,我想我现在才明白你的想法。看起来不错,非常感谢 <3
0赞 mpasko256 12/2/2017
我已经更新了代码,但得到了一个结果,即以 1 和 7 开头的项目落在同一个堆中。如果他们的 x 差是 2 而 y 是 1,应该没问题吗?
0赞 Daniel Beck 12/2/2017 #2

如果我们命名输入的部分,则此代码将其展平为 ,排序依据 ,然后将块备份到组中:[[z,[[x,y],[x,y]],...][[x,y,z],...]x

var my_array= [
    [2, [[9, 10]]],
    [5, [[10, 11]]],
    [4, [[11, 9]]],
    [1, [[19, 2], [41, 10]]],
    [7, [[17, 3]]],
    [0, [[11, 4], [18, 5]]]
]

var rearrange = function(arr) {
  // flatten the input structure into [[x,y,z], [x,y,z]]:
  var simpler = [];
  arr.forEach(function(row) {
    row[1].forEach(function(pair) {
      simpler.push([pair[0],pair[1],row[0]]);
    })
  });
  // sort by x:
  simpler = simpler.sort(function(a,b) {
    return a[0]-b[0]
  });
  // console.log(simpler);
  // Now group by x±2, into [ [z,[x,y]],[z,[x,y]] ]
  var output = [];
  var group = [];
  var latestX=simpler[0][0];
  simpler.forEach(function(row) {
    if (row[0] > latestX + 5) {
      // start a new group
      latestX = row[0];
      if (group.length > 0) {
        output.push(group);
        group = [];
      }
    }
    group.push([row[2],[row[0],row[1]]]);  
  });
  output.push(group); // catch the last group
  return output;

}
console.log(rearrange(my_array));

评论

0赞 Jonas0000 12/2/2017
您的解决方案看起来绝对没问题。非常感谢丹尼尔。如果你喜欢再次帮助我,看看我上面的编辑。提前致谢,问候
0赞 Daniel Beck 12/2/2017
那是。。。对这个问题的相当大的改变。
0赞 Jonas0000 12/2/2017
你说得完全正确,丹尼尔。没关系,如果你不喜欢的话,我稍后会自己看看。但是,非常感谢!
0赞 Nina Scholz 12/2/2017 #3

如果值在组节点的所需范围内,则可以单点检查所有组。如果不在任何组中,则生成一个新组并存储该点。继续操作,直到没有更多可用点。

var array = [[2, [[9, 10]]], [5, [[10, 11]]], [4, [[11, 9]]], [1, [[19, 2], [41, 10]]], [7, [[17, 3]]], [0, [[11, 4], [18, 5]]]],
    normalized = array.reduce(function (r, a) {
        return r.concat(a[1].map(function (b) { return [a[0], b]; }));
    }, []),
    grouped = [],
    i, j, k,
    updated;

loop: while (normalized.length) {
    if (!updated) {
        grouped.push([normalized.shift()]);
    }
    updated = false;
    for (i = 0; i < normalized.length; i++) {
        for (j = 0; j < grouped.length; j++) {
            for (k = 0; k < grouped[j].length; k++) {
                if (Math.abs(normalized[i][1][0] - grouped[j][k][1][0]) <= 2 && Math.abs(normalized[i][1][1] - grouped[j][k][1][1]) <= 1) {
                    grouped[j].push(normalized.splice(i, 1)[0]);
                    updated = true;
                    continue loop;
                }
            }
        }
    }
}

console.log(grouped.map(function (a) { return JSON.stringify(a); }));
.as-console-wrapper { max-height: 100% !important; top: 0; }

旧版本仅一尺寸。

您可以通过以下方式采取直接的方法

  • 归一化值,
  • 排序值,
  • 增量小于或等于 2 的分组。

var array = [[2, [[9, 10]]], [5, [[10, 11]]], [4, [[11, 9]]], [1, [[19, 2], [41, 10]]], [7, [[17, 3]]], [0, [[11, 4], [18, 5]]]],
    grouped = array
        .reduce(function (r, a) {
            return r.concat(a[1].map(function (b) { return [a[0], b]; }));
        }, [])
        .sort(function (a, b) {
            return a[1][0] - b[1][0];
        })
        .reduce(function (r, a, i, aa) {
            if (aa[i - 1] && a[1][0] - aa[i - 1][1][0] <= 2) {
                r[r.length - 1].push(a);
            } else {
                r.push([a]);
            }
            return r;
        }, []);

console.log(grouped);
.as-console-wrapper { max-height: 100% !important; top: 0; }