javascript中数组中重复数组的计数
我有一个数组,如下所示:javascript中数组中重复数组的计数,javascript,arrays,Javascript,Arrays,我有一个数组,如下所示: [[3, 4], [1, 2], [3, 4]] 我希望创建一个新的数组,该数组没有重复项,并且具有第一个数组中每个元素的出现次数计数: [[3,4,2], [1,2,1]] 以下是我到目前为止的情况: var alreadyAdded = 0; dataset.forEach(function(data) { From = data[0]; To = data[1]; index = 0; newDataSet.forEach(func
[[3, 4], [1, 2], [3, 4]]
我希望创建一个新的数组,该数组没有重复项,并且具有第一个数组中每个元素的出现次数计数:
[[3,4,2], [1,2,1]]
以下是我到目前为止的情况:
var alreadyAdded = 0;
dataset.forEach(function(data) {
From = data[0];
To = data[1];
index = 0;
newDataSet.forEach(function(newdata) {
newFrom = newData[0];
newTo = newData[1];
// check if the point we are looking for is already added to the new array
if ((From == newFrom) && (To == newTo)) {
// if it is, increment the count for that pair
var count = newData[2];
var newCount = count + 1;
newDataSet[index] = [newFrom, newTo, newCount];
test = "reached here";
alreadyAdded = 1;
}
index++;
});
// the pair was not already added to the new dataset, add it
if (alreadyAdded == 0) {
newDataSet.push([From, To, 1]);
}
// reset alreadyAdded variable
alreadyAdded = 0;
});
我对Javascript非常陌生,有人能帮我解释一下我做错了什么吗?我确信有一种更简洁的方法可以做到这一点,但是我在javascript中找不到一个处理重复数组的示例。修复一个拼写错误后,我在调试器中尝试了您的解决方案;它起作用了 修复了内部forEach循环变量名以匹配大小写。还添加了一些var关键字
var alreadyAdded = 0;
dataset.forEach(function (data) {
var From = data[0];
var To = data[1];
var index = 0;
newDataSet.forEach(function (newData) {
var newFrom = newData[0];
var newTo = newData[1];
// check if the point we are looking for is already added to the new array
if ((From == newFrom) && (To == newTo)) {
// if it is, increment the count for that pair
var count = newData[2];
var newCount = count + 1;
newDataSet[index] = [newFrom, newTo, newCount];
test = "reached here";
alreadyAdded = 1;
}
index++;
});
// the pair was not already added to the new dataset, add it
if (alreadyAdded == 0) {
newDataSet.push([From, To, 1]);
}
// reset alreadyAdded variable
alreadyAdded = 0;
});
假设子数组项的顺序很重要,假设您的子数组可以是可变长度的,并且可以包含除数字以外的项,下面是解决此问题的一种相当通用的方法。目前需要ECMA5兼容性,但要使其在ECMA3上工作并不困难 Javascript
// Create shortcuts for prototype methods
var toClass = Object.prototype.toString.call.bind(Object.prototype.toString),
aSlice = Array.prototype.slice.call.bind(Array.prototype.slice);
// A generic deepEqual defined by commonjs
// http://wiki.commonjs.org/wiki/Unit_Testing/1.0
function deepEqual(a, b) {
if (a === b) {
return true;
}
if (toClass(a) === '[object Date]' && toClass(b) === '[object Date]') {
return a.getTime() === b.getTime();
}
if (toClass(a) === '[object RegExp]' && toClass(b) === '[object RegExp]') {
return a.toString() === b.toString();
}
if (a && typeof a !== 'object' && b && typeof b !== 'object') {
return a == b;
}
if (a.prototype !== b.prototype) {
return false;
}
if (toClass(a) === '[object Arguments]') {
if (toClass(b) !== '[object Arguments]') {
return false;
}
return deepEqual(aSlice(a), aSlice(b));
}
var ka,
kb,
length,
index,
it;
try {
ka = Object.keys(a);
kb = Object.keys(b);
} catch (eDE) {
return false;
}
length = ka.length;
if (length !== kb.length) {
if (Array.isArray(a) && Array.isArray(b)) {
if (a.length !== b.length) {
return false;
}
} else {
return false;
}
} else {
ka.sort();
kb.sort();
for (index = 0; index < length; index += 1) {
if (ka[index] !== kb[index]) {
return false;
}
}
}
for (index = 0; index < length; index += 1) {
it = ka[index];
if (!deepEqual(a[it], b[it])) {
return false;
}
}
return true;
};
// Recursive function for counting arrays as specified
// a must be an array of arrays
// dupsArray is used to keep count when recursing
function countDups(a, dupsArray) {
dupsArray = Array.isArray(dupsArray) ? dupsArray : [];
var copy,
current,
count;
if (a.length) {
copy = a.slice();
current = copy.pop();
count = 1;
copy = copy.filter(function (item) {
var isEqual = deepEqual(current, item);
if (isEqual) {
count += 1;
}
return !isEqual;
});
current.push(count);
dupsArray.push(current);
if (copy.length) {
countDups(copy, dupsArray);
}
}
return dupsArray;
}
var x = [
[3, 4],
[1, 2],
[3, 4]
];
console.log(JSON.stringify(countDups(x)));
在上,根据您迭代的数据集有多大,我会小心地循环多次。通过为原始数据集中的每个元素创建一个“索引”,然后使用它引用分组中的元素,可以避免这样做。这就是我解决问题时采取的方法。您可以在JSFIDLE上看到它。我使用
Array.prototype.reduce
创建一个对象文本,其中包含来自原始数据集的元素分组。然后我迭代它的键来创建最终的分组
var dataSet = [[3,4], [1,2], [3,4]],
grouping = [],
counts,
keys,
current;
counts = dataSet.reduce(function(acc, elem) {
var key = elem[0] + ':' + elem[1];
if (!acc.hasOwnProperty(key)) {
acc[key] = {elem: elem, count: 0}
}
acc[key].count += 1;
return acc;
}, {});
keys = Object.keys(counts);
for (var i = 0, l = keys.length; i < l; i++) {
current = counts[keys[i]];
current.elem.push(current.count);
grouping.push(current.elem);
}
console.log(grouping);
var数据集=[[3,4]、[1,2]、[3,4]],
分组=[],
计数,
钥匙,
现在的
计数=数据集.reduce(函数(acc、elem){
var key=elem[0]+':'+elem[1];
如果(!acc.hasOwnProperty(键)){
acc[键]={elem:elem,计数:0}
}
acc[键]。计数+=1;
返回acc;
}, {});
键=对象。键(计数);
对于(变量i=0,l=keys.length;i
const x=[[3,4]、[1,2]、[3,4];
具有重复计数的常数=[
…x
.map(JSON.stringify)
.reduce((acc,v)=>acc.set(v,(acc.get(v)| | 0)+1),new Map())
.条目()
].map(([k,v])=>JSON.parse(k).concat(v));
console.log(具有重复计数)
是否将[3,4]
和[4,3]
视为相同或订单是否重要?您能否澄清您预期的结果?我不明白你是怎么得到的[[3,4,2],[1,2,1]
它看起来不像[3,4]
和[4,3]
一样。如果查看OP代码中使用的变量,每个数组似乎只包含两个元素,第一个元素是事件前的位置,最后一个元素是事件后的位置。因此,从3
移动到4
与从4
移动到3
并不相同。谢谢科林!您的解决方案更加优雅,运行速度更快,因为数据集确实相当大。reduce函数似乎非常有用,我可能会反复使用它:)谢谢supertopi!没想到这是一个小小的打字错误!
var dataSet = [[3,4], [1,2], [3,4]],
grouping = [],
counts,
keys,
current;
counts = dataSet.reduce(function(acc, elem) {
var key = elem[0] + ':' + elem[1];
if (!acc.hasOwnProperty(key)) {
acc[key] = {elem: elem, count: 0}
}
acc[key].count += 1;
return acc;
}, {});
keys = Object.keys(counts);
for (var i = 0, l = keys.length; i < l; i++) {
current = counts[keys[i]];
current.elem.push(current.count);
grouping.push(current.elem);
}
console.log(grouping);