【问题标题】:Javascript get the index of the first and last occurrence of a duplicate element in an arrayJavascript获取数组中第一次和最后一次出现重复元素的索引
【发布时间】:2015-10-11 00:34:10
【问题描述】:

我有一个点数组(经纬度坐标),其中一些是重复的。对于重复项,重复项将在数组中准确重复四次。我想知道数组中第一次和最后一次出现重复项的索引。到目前为止,这就是我所做的:

我正在检查每个元素和它旁边的元素(这是一个未排序的数组)

for(var i = 0; i < points.length; i++) {
  for(var j=i+1; j<points.length; j++) {
    if(points[i] == points[j]) {
      var firstOccurrence = points.indexOf(points[i]);
      var lastOccurrence = points.indexOf(points[i], j+1);
      console.log(firstOccurrence);
      console.log(lastOccurrence);
    }
   }
 }

firstOccurrence 正确给出了第一个重复出现的索引,但打印了四次相同的索引(可能是通过 for 循环循环?)。 lastOccurrence 也打印正确,但第一次打印正确的索引,其余 3 次打印“-1”。我在这里做错了什么?我对javascript比较陌生。

编辑: 如果我做一个

    if(firstOccurrence) {
      console.log(firstOccurrence); //I would do something else here too apart from printing
    }

它留下第一个重复的第一次出现并打印剩余的索引。例如,如果我的数组是:

 points = [4,4,1,8,0,4,4,5,5,2,7,9,5,5,3,3,10,33,21,3,3];

然后,它打印出来

   7
   14

省略第一个重复出现的索引为 0。是因为内部 for 循环中的 j = i+1 吗?

【问题讨论】:

  • 你想要一个元素的重复索引,还是数组中每个重复的索引?
  • 我想要数组中每个重复项的第一个和最后一个重复索引。例如,如果点 = [4,4,1,8,0,4,4,5,5,2,7,9,5,5,3,3,10,33,21,3,3],那么我想要 4、5 和 3 的第一个和最后一个重复索引,对于 4,这将是 0,6-->; 7,13--> 5 和 14,20--> 3。
  • 我认为我的代码正在做它应该做的事情,除了我怀疑内部 for 循环(j)。 console.log 打印输出 4 次,每次重复。可能是因为每个重复出现 4 次?)
  • 您的代码非常不一致,假设您有一个 [4,4,4,4] 数组。您可以通过您的代码看到它通过索引 0,1 并打印,0,2 并打印,0,3 依此类推。
  • 它应该只打印 0,3。

标签: javascript arrays indexing duplicates


【解决方案1】:

查找重复项的一种有效方法(无需为每个元素循环遍历数组)是找到一种散列坐标的方法。然后,您可以使用 reducer 对每个数组的所有索引进行分组,并轻松找到重复的坐标。

例如,假设您的数据如下所示:

var data = [
  {lat: 120, lon: 30},
  {lat: 122, lon: 31},
  {lat: 120, lon: 30},
  ...
];

// Create a function which maps each element to a hashable string

function make(d) {
  return d.lat + ':' + d.lon;
}

// Create a reducer which gathers indexes

// here acc is the accumulated object which starts at {}
// d is each item in the array, and i is the index

data.reduce(function(acc, d, i) {
  var key = make(d);
  acc[key] = acc[key].concat(i) || [i] // gather indexes per element
  return acc;
}, {});

现在您有了一个对象,其中包含键值对的所有元素及其在原始且未更改的数组中的索引。

编辑:在 reduce 函数中,我在 acc 中使用 d 而不是 key。

【讨论】:

    【解决方案2】:

    这是我的两个版本的解决方案: 第一个版本很容易理解,但它打印了 4 次重复项。 第二个版本使用 @Jonah Williams 提出的 map reduce

    function printDuplicatesSimple(points) {
        var first, last;
        for (var i = 0; i < points.length; i++) {
            first = points.indexOf(points[i]);
            last = points.lastIndexOf(points[i]);
            print(duplicateToString(first, last));
        }
    }
    
    function duplicateToString(first, last) {
        return "(" + first + "," + last + ")";
    }
    
    function makeKey(i, arr) {
        var first = points.indexOf(points[i]),
            last = points.lastIndexOf(points[i]);
    
        return first === last ? -1 : duplicateToString(first, last);
    }
    
    function printDuplicatesMapReduce(points) {
        var res = points.reduce(function(dict, currentItem, index, arr) {
            var key = makeKey(index, arr);
            if (key === -1) {
                return dict; //skip
            }
            if (dict.indexOf(key) === -1) {
                dict.push(key);
            }
    
            return dict;
        }, []);
    
    
        print(res);
    
    }
    
    var points = [4, 4, 1, 8, 0, 4, 4, 5, 5, 2, 7, 9, 5, 5, 3, 3, 10, 33, 21, 3, 3];
    printDuplicatesSimple(points);
    

    简单版输出:(0,6) (0,6) (2,2) (3,3) (4,4) (0,6) (0,6) (7,13) (7,13) (9,9) (10,10) (11,11) (7,13) (7,13) (14,20) (14,20) (16,16) (17,17) (18,18) (14,20) (14,20)

    Map reduce 版本输出: (0,6),(7,13),(14,20)

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2018-05-21
      • 1970-01-01
      • 1970-01-01
      • 2020-10-13
      • 2019-04-29
      • 1970-01-01
      • 1970-01-01
      • 2014-07-15
      相关资源
      最近更新 更多