Javascript 从阵列中计数和删除重复项的快速方法
我有一个包含重复项的数组Javascript 从阵列中计数和删除重复项的快速方法,javascript,arrays,sorting,duplicates,Javascript,Arrays,Sorting,Duplicates,我有一个包含重复项的数组 array = ["String 1", "string 2", "STRING 1", "String 2", "String 3", "String 1"] 我想去掉重复项(不区分大小写),并创建一个新的数组来计算重复项 在其中一个答案中,我看到了以下功能: function count_array(arr) { var a = [], b = [], prev; arr.sort(); for ( var i = 0; i < a
array = ["String 1", "string 2", "STRING 1", "String 2", "String 3", "String 1"]
我想去掉重复项(不区分大小写),并创建一个新的数组来计算重复项
在其中一个答案中,我看到了以下功能:
function count_array(arr) {
var a = [], b = [], prev;
arr.sort();
for ( var i = 0; i < arr.length; i++ ) {
if ( arr[i] !== prev ) {
a.push(arr[i]);
b.push(1);
} else {
b[b.length-1]++;
}
prev = arr[i];
}
return [a, b];
}
如果不区分大小写,我希望string1、string1、string1、string1
的所有实例都被视为string1
对于大型阵列,还有更好的方法吗?例如,数组长度为10K .sort()
是一个O(N log N)
过程-如果您需要对结果进行排序,请在最后进行,如果您担心速度问题。如果不需要对结果进行排序,则使用集合
(或映射
)检查重复项,而不是检查排序数组中相邻标记中的类似项
array=[“字符串1”、“字符串2”、“字符串1”、“字符串2”、“字符串3”、“字符串1”]
函数计数\u数组(arr){
常量结果=[];
常量映射=新映射();
arr.forEach((str)=>{
const lower=str.toLowerCase();
const currCount=map.get(下)| | 0;
如果(!currCount){
结果:推(str);
}
映射集(较低,currCount+1);
});
log([…map.values()]);
返回result.sort();
}
log(计数数组(数组))代码>使用字符串作为键,将外观数作为值,将字符串数组缩减为对象。使用Object.keys()
获取第一个数组,使用Object.values()
获取第二个数组:
常量数组=[“字符串1”、“字符串2”、“字符串1”、“字符串2”、“字符串3”、“字符串1”]
常量计数=数组。减少((r,s)=>{
const key=s[0].toUpperCase()+s.substring(1).toLowerCase();
r[键]=(r[键]| 0)+1;
返回r;
}, {});
const first=对象键(计数);
常数秒=对象值(计数);
console.log(第一);
console.log(第二个)代码>您可以对一些函数进行排序,并使用计数来过滤未初始化的值
const
normalize=s=>s.toLowerCase(),
getFirst=a=>a,
映射计数=(m,k)=>m.set(k,(m.get(k)| | 0)+1),
数组=[“字符串1”、“字符串2”、“字符串1”、“字符串2”、“字符串3”、“字符串1”],
地图=新地图,
array1=array.filter(v=>(k=>getFirst(!map.has(k),mapCount(map,k)))(normalize(v)),
array2=Array.from(map.values());
控制台日志(array1);
控制台日志(array2)
如果您询问最快的方法,则应在Big-O(N)
中渐进地进行:
首先,您需要一个散列映射来存储所有过去的字符串李>
其次,您需要迭代给定的数组,将其值放入哈希映射中李>
最后,您需要在每次满足哈希映射时增加该字符串的计数
它可以这样实现:
const arr = [...];
const map = {};
for (let i = 0; i <= arr.length - 1; i++) {
const str = arr[i].toLowerCase();
if (str in map) {
map[str]++;
// keep in mind that removing element from an array costs O(N)
arr[i] = undefined;
} else {
map[str] = 1;
}
}
// now you have the hash map that represents all strings and its numbers of appearances in the given array
doSomething(map);
// finally return filtered result
return arr.filter(str => str !== undefined);
const arr=[…];
常量映射={};
for(设i=0;i str!==未定义);
这可以使用数组简洁地完成。reduce
创建一个映射,其键是数组的小写项,值是它们的计数。然后使用Object.keys()
获取唯一项,并使用Object.values()
获取计数:
常量数组=[“字符串1”、“字符串2”、“字符串1”、“字符串2”、“字符串3”、“字符串1];
常量映射=数组。减少((acc,x)=>{
const xLower=x.tolocalLowercase();
acc[xLower]=(acc[xLower]| | 0)+1;
返回acc;
}, {});
控制台日志(map);
console.log(Object.keys(map));
console.log(Object.values(map))代码>感谢您的深入解释,您的答案不包括项目吗?我想得到第二个数组,它对应于数组1Oh中的重复数,您也需要计数,使用映射
而不是集合来保持跟踪。是否可以在两个单独的数组中获得它们?我在另一个函数中使用返回数组,该函数接受两个不同的数组。只需从映射中的每个数组中获取第二项,即可获得对应于每个字符串的计数。我认为Object.keys
是O(n)
所以我不确定大型阵列的性能?因为您需要一个n
项的阵列-O(n)
非常好。谢谢您,在您的回答中,是否可以从重复计数的最高数量订购到最低数量?请参阅更新。注意-Array.sort()
的复杂性是O(n log(n))
const arr = [...];
const map = {};
for (let i = 0; i <= arr.length - 1; i++) {
const str = arr[i].toLowerCase();
if (str in map) {
map[str]++;
// keep in mind that removing element from an array costs O(N)
arr[i] = undefined;
} else {
map[str] = 1;
}
}
// now you have the hash map that represents all strings and its numbers of appearances in the given array
doSomething(map);
// finally return filtered result
return arr.filter(str => str !== undefined);