Javascript 数组 ab=ba
Javascript arrays ab=ba
如果我有一个像这样的多维数组:[[a,b],[a,c],[b,a],[b,c],[c,a],[c,b]]
我如何遍历并删除 [a,b]
与 [b,a]
相同的重复项。
还有,这个阵法其实很大,有几万个。 for 循环必须向后执行,因为数组长度会在每次迭代时缩小。我什至不确定每个循环是否适用于此。我真的不知道如何开始。
另外,我搜索了大约一个小时,我什至不知道如何表达它。
根据我的理解,您想从父数组中删除任何包含相同对象集而不考虑顺序的子数组,应该这样做 是一些代码:
function getId(obj) { // apparently these objects have identifiers
return obj._id; // I'm testing with MongoDB documents
}
function arraysEqual(a, b) {
if (a === b) { return true; }
if (a == null || b == null) { return false; }
if (a.length != b.length) { return false; }
aIds = []; bIds = [];
for (var i = 0; i < a.length; i++) {
aIds.push(getId(a[i])); bIds.push(getId(b[i]));
}
aIds.sort(); bIds.sort();
for ( var i = 0; i < aIds.length; i++ ) {
if(aIds[i] !== bIds[i]) { return false; }
}
return true;
}
function removeRepeats(list) {
var i, j;
for (i=0; i < list.length; i++) {
for (j=i+1; j < list.length; j++) {
if (arraysEqual(list[i], list[j])) {
list.splice(j,1);
}
}
}
}
removeRepeats
函数遍历每个元素并将它与它后面的每个元素进行比较。 arraysEqual
function simply returns true if the arrays are equal. The isEquivalent
function 应该测试对象等价性。如该网页上所述,有一些库可以测试对象等效性。如果您可以添加这些库,则可以将 isEquivalent
函数替换为 _.isEqual
。
***
* Turns out the OP has objects in his list, so this approach won't
* work in that case. I'll leave this for future reference.
***
var foo = [['a','b'],['a','c'],['b','a'],['b','c'],['c','a'],['c','b']];
function removeRepeats(list) {
var i;
var b = [];
var _c = [];
for (i = 0; i < list.length; i++) {
var a = list[i].sort();
var stra = a.join("-");
if(_c.indexOf(stra) === -1) {
b.push(a);
_c.push(stra);
}
}
return b;
}
console.log(removeRepeats(foo));
这不是我编写过的最漂亮的代码,但我想它应该足以让您入门。我正在做的是创建两个新数组,b
和 _c
。 b
将是没有重复的数组。 _c
是一个辅助数组,其中包含所有已处理为字符串的唯一对,因此我可以在遍历 list
.
时进行简单的字符串比较
我想我要尝试用不同的方法来解决这个问题。我还认为它会比提出的一些解决方案更快(尽管我们当然需要对其进行测试和基准测试)。
首先,我们为什么不利用 javascript 数组和对象的面向散列的特性?我们可以创建一个包含关系的对象(为了创建一种地图),并将那些尚未存储的关系存储在一个新数组中。使用这种方法,对象也没有问题,我们只需为每个对象请求一个标识符或散列或其他任何东西。此标识符必须使它们之间的关系成为可能。
更新
- 脚本现在控制重复元素的可能性f.e [[a,b],[a,b]]
- 脚本现在控制具有相同对象的元素重复的可能性 f.e [[a,a],[a,a][a,a]] 会 return [a,一个]
代码:
var temp = {},
massive_arr = [['a','b'],['a','c'],['a','d'], ['b','a'],['b','c'],['b','d'],['c','a'],['c','b'],['c','d']],
final_arr = [],
i = 0,
id1,
id2;
for( ; i < massive_arr.length; i++ ) {
id0 = objectIdentifier(massive_arr[i][0]);// Identifier of first object
id1 = objectIdentifier(massive_arr[i][1]);// Identifier of second object
if(!temp[id0]) {// If the attribute doesn't exist in the temporary object, we create it.
temp[id0] = {};
temp[id0][id1] = 1;
} else {// if it exists, we add the new key.
temp[id0][id1] = 1;
}
if( id0 === id1 && !temp[id0][id1+"_bis"] ) {// Especial case [a,a]
temp[id0][id1+"_bis"] = 1;
final_arr.push(massive_arr[i]);
continue;// Jump to next iteration
}
if (!temp[id1]) {// Store element and mark it as stored.
temp[id1] = {};
temp[id1][id0] = 1;
final_arr.push(massive_arr[i]);
continue;// Jump to next iteration
}
if (!temp[id1][id0]) {// Store element and mark it as stored.
temp[id1][id0] = 1;
final_arr.push(massive_arr[i]);
}
}
console.log(final_arr);
function objectIdentifier(obj) {
return obj;// You must return a valid identifier for the object. For instance, obj.id or obj.hashMap... whatever that identifies it unequivocally.
}
你可以测试一下here
第二次更新
虽然这不是最初的要求,但我稍微更改了方法以使其适应长度为 n 的元素(如果需要,n 可以变化)。
由于依赖排序为地图生成有效键,因此此方法速度较慢。即便如此,我觉得也够快了。
var temp = {},
massive_arr = [
['a', 'a', 'a'], //0
['a', 'a', 'b'], //1
['a', 'b', 'a'],
['a', 'a', 'b'],
['a', 'c', 'b'], //2
['a', 'c', 'd'], //3
['b', 'b', 'c'], //4
['b', 'b', 'b'], //5
['b', 'b', 'b'],
['b', 'c', 'b'],
['b', 'c', 'd'], //6
['b', 'd', 'a'], //7
['c', 'd', 'b'],
['c', 'a', 'c'], //8
['c', 'c', 'a'],
['c', 'd', 'a', 'j'], // 9
['c', 'd', 'a', 'j', 'k'], // 10
['c', 'd', 'a', 'o'], //11
['c', 'd', 'a']
],
final_arr = [],
i = 0,
j,
ord,
key;
for (; i < massive_arr.length; i++) {
ord = [];
for (j = 0; j < massive_arr[i].length; j++) {
ord.push(objectIdentifier(massive_arr[i][j]));
}
ord.sort();
key = ord.toString();
if (!temp[key]) {
temp[key] = 1;
final_arr.push(massive_arr[i]);
}
}
console.log(final_arr);
function objectIdentifier(obj) {
return obj;
}
可以测试here
如果我有一个像这样的多维数组:[[a,b],[a,c],[b,a],[b,c],[c,a],[c,b]]
我如何遍历并删除 [a,b]
与 [b,a]
相同的重复项。
还有,这个阵法其实很大,有几万个。 for 循环必须向后执行,因为数组长度会在每次迭代时缩小。我什至不确定每个循环是否适用于此。我真的不知道如何开始。
另外,我搜索了大约一个小时,我什至不知道如何表达它。
根据我的理解,您想从父数组中删除任何包含相同对象集而不考虑顺序的子数组,应该这样做 是一些代码:
function getId(obj) { // apparently these objects have identifiers
return obj._id; // I'm testing with MongoDB documents
}
function arraysEqual(a, b) {
if (a === b) { return true; }
if (a == null || b == null) { return false; }
if (a.length != b.length) { return false; }
aIds = []; bIds = [];
for (var i = 0; i < a.length; i++) {
aIds.push(getId(a[i])); bIds.push(getId(b[i]));
}
aIds.sort(); bIds.sort();
for ( var i = 0; i < aIds.length; i++ ) {
if(aIds[i] !== bIds[i]) { return false; }
}
return true;
}
function removeRepeats(list) {
var i, j;
for (i=0; i < list.length; i++) {
for (j=i+1; j < list.length; j++) {
if (arraysEqual(list[i], list[j])) {
list.splice(j,1);
}
}
}
}
removeRepeats
函数遍历每个元素并将它与它后面的每个元素进行比较。 arraysEqual
function simply returns true if the arrays are equal. The isEquivalent
function 应该测试对象等价性。如该网页上所述,有一些库可以测试对象等效性。如果您可以添加这些库,则可以将 isEquivalent
函数替换为 _.isEqual
。
***
* Turns out the OP has objects in his list, so this approach won't
* work in that case. I'll leave this for future reference.
***
var foo = [['a','b'],['a','c'],['b','a'],['b','c'],['c','a'],['c','b']];
function removeRepeats(list) {
var i;
var b = [];
var _c = [];
for (i = 0; i < list.length; i++) {
var a = list[i].sort();
var stra = a.join("-");
if(_c.indexOf(stra) === -1) {
b.push(a);
_c.push(stra);
}
}
return b;
}
console.log(removeRepeats(foo));
这不是我编写过的最漂亮的代码,但我想它应该足以让您入门。我正在做的是创建两个新数组,b
和 _c
。 b
将是没有重复的数组。 _c
是一个辅助数组,其中包含所有已处理为字符串的唯一对,因此我可以在遍历 list
.
我想我要尝试用不同的方法来解决这个问题。我还认为它会比提出的一些解决方案更快(尽管我们当然需要对其进行测试和基准测试)。
首先,我们为什么不利用 javascript 数组和对象的面向散列的特性?我们可以创建一个包含关系的对象(为了创建一种地图),并将那些尚未存储的关系存储在一个新数组中。使用这种方法,对象也没有问题,我们只需为每个对象请求一个标识符或散列或其他任何东西。此标识符必须使它们之间的关系成为可能。
更新
- 脚本现在控制重复元素的可能性f.e [[a,b],[a,b]]
- 脚本现在控制具有相同对象的元素重复的可能性 f.e [[a,a],[a,a][a,a]] 会 return [a,一个]
代码:
var temp = {},
massive_arr = [['a','b'],['a','c'],['a','d'], ['b','a'],['b','c'],['b','d'],['c','a'],['c','b'],['c','d']],
final_arr = [],
i = 0,
id1,
id2;
for( ; i < massive_arr.length; i++ ) {
id0 = objectIdentifier(massive_arr[i][0]);// Identifier of first object
id1 = objectIdentifier(massive_arr[i][1]);// Identifier of second object
if(!temp[id0]) {// If the attribute doesn't exist in the temporary object, we create it.
temp[id0] = {};
temp[id0][id1] = 1;
} else {// if it exists, we add the new key.
temp[id0][id1] = 1;
}
if( id0 === id1 && !temp[id0][id1+"_bis"] ) {// Especial case [a,a]
temp[id0][id1+"_bis"] = 1;
final_arr.push(massive_arr[i]);
continue;// Jump to next iteration
}
if (!temp[id1]) {// Store element and mark it as stored.
temp[id1] = {};
temp[id1][id0] = 1;
final_arr.push(massive_arr[i]);
continue;// Jump to next iteration
}
if (!temp[id1][id0]) {// Store element and mark it as stored.
temp[id1][id0] = 1;
final_arr.push(massive_arr[i]);
}
}
console.log(final_arr);
function objectIdentifier(obj) {
return obj;// You must return a valid identifier for the object. For instance, obj.id or obj.hashMap... whatever that identifies it unequivocally.
}
你可以测试一下here
第二次更新
虽然这不是最初的要求,但我稍微更改了方法以使其适应长度为 n 的元素(如果需要,n 可以变化)。
由于依赖排序为地图生成有效键,因此此方法速度较慢。即便如此,我觉得也够快了。
var temp = {},
massive_arr = [
['a', 'a', 'a'], //0
['a', 'a', 'b'], //1
['a', 'b', 'a'],
['a', 'a', 'b'],
['a', 'c', 'b'], //2
['a', 'c', 'd'], //3
['b', 'b', 'c'], //4
['b', 'b', 'b'], //5
['b', 'b', 'b'],
['b', 'c', 'b'],
['b', 'c', 'd'], //6
['b', 'd', 'a'], //7
['c', 'd', 'b'],
['c', 'a', 'c'], //8
['c', 'c', 'a'],
['c', 'd', 'a', 'j'], // 9
['c', 'd', 'a', 'j', 'k'], // 10
['c', 'd', 'a', 'o'], //11
['c', 'd', 'a']
],
final_arr = [],
i = 0,
j,
ord,
key;
for (; i < massive_arr.length; i++) {
ord = [];
for (j = 0; j < massive_arr[i].length; j++) {
ord.push(objectIdentifier(massive_arr[i][j]));
}
ord.sort();
key = ord.toString();
if (!temp[key]) {
temp[key] = 1;
final_arr.push(massive_arr[i]);
}
}
console.log(final_arr);
function objectIdentifier(obj) {
return obj;
}
可以测试here