简体   繁体   English

如何迭代对象中所有唯一的条目对?

[英]How can I iterate over all unique pairs of entries in an object?

I currently have an array data structure that I iterate over like this, calling foo on each unique pair of elements. 我目前有一个数组数据结构,我迭代这样,在每个独特的元素对上调用foo

for(var i = 0; i < arr.length; i++) {
    for(var j = i + 1; j < arr.length; j++) {
        foo(arr[i], arr[j]);
    }
}

However, I've realized that I'd rather use an object instead of an array, since I can then add and remove elements by name very easily. 但是,我意识到我宁愿使用一个对象而不是一个数组,因为我可以很容易地按名称添加和删除元素。

However, I can't see an obvious way to iterate over such an object. 但是,我看不到一种明显的方法来迭代这样的对象。 The closest I can get is: 我能得到的最接近的是:

for(i in obj) {
    for(j in obj) {
        foo(obj[i], obj[j]);
    }
}

Obviously, this will do each pair twice, and even produce a pair of identical elements. 显然,这将每对做两次,甚至产生一对相同的元素。 Is there an easy way to iterate over an object in the same way as I do in the array in my first code sample? 是否有一种简单的方法来迭代对象,就像我在第一个代码示例中的数组中一样?

Update: 更新:

Performance testing the solutions on jsperf . jsperf上测试解决方案的性能。

My solution that was at first written as a comment: 我的解决方案最初是作为评论写的:

Add an if (i < j) condition in the inner loop. 在内循环中添加if (i < j)条件。 It might not be the best solution, but it would work as long as the foo function does the same thing for foo(2, 10) and foo(10, 2) : 它可能不是最好的解决方案,但只要foo函数对foo(2, 10) foo(10, 2) foo(2, 10)foo(10, 2) foo(2, 10)执行相同的操作,它就会起作用:

for(i in obj) {
    for(j in obj) {
        if (i < j) {
            foo(obj[i], obj[j]);
        }
    }
}

Assuming I understand your question... maybe check to see if the value has already been visited by the outer loop? 假设我理解你的问题...也许检查一下外循环是否已经访问过该值?

var visited = {}
for(i in obj) {
    visited[i] = true;
    for(j in obj) {
        if(j in visited){ continue; }
        foo(obj[i], obj[j]);
    }
}

Use Object.keys() to get the list of keys out as an array: 使用Object.keys()以数组的形式获取键列表:

keys = Object.keys();
for(i=0;i<keys.length;i++) {
    for(j=i+1;j<keys.length;j++) {
        foo(obj[keys[i]], obj[keys[j]]);
    }
}

Maybe You can try unset used objects: 也许您可以尝试取消设置未使用的对象:

for(i in obj) {
    var a = obj[i];
    delete obj[i];
    for(j in obj) {
        foo(a, obj[j]);
    }
}

http://jsfiddle.net/bXcvb/ http://jsfiddle.net/bXcvb/

If you need to original obj in tact see: How do I correctly clone a JavaScript object? 如果您需要原始obj,请参阅: 如何正确克隆JavaScript对象?

You can push the object keys into an array: 您可以将对象键推送到数组中:

var obj_keys = [];
for (i in obj) {
  obj_keys.push(i);
}

for(i = 0; i < obj_keys.length; ++i) {
    for(j = i + 1; j < obj_keys.length; ++j) {
        foo(obj[obj_keys[i]], obj[obj_keys[j]]);
    }
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM