【问题标题】:Filter array based on string content and repetition count with jQuery使用 jQuery 根据字符串内容和重复计数过滤数组
【发布时间】:2020-06-15 04:52:47
【问题描述】:

我会解释需要什么。希望您能提供帮助。 我有一个数组。首先,两个数字是无关紧要的权重,然后是空格和一个电子邮件

var arr= new Array("10 firstemail@email.com","15 secondemail@email.com","25 secondemail@email.com","35 secondemail@email.com","15 firstemail@email.com"); // huge array with many emails not just 2

我想要一个新数组,按电子邮件过滤,重复次数最少。

应该是:

["10 firstemail@email.com","15 firstemail@email.com"];

因为 firstemail@email.com 只重复 2 次,而 secondemail@email.com 重复 3 次。

使用的浏览器是带有 jQ​​uery 的 IE8(必须使用 jQuery,因为原生 .filter() 不起作用)

我知道这可能可以通过几个 foreach/fors 来完成,但我正在寻找优化的解决方案。

例如:

new_arr = $(arr).filter(function (str) { return arr[str].indexOf("firstemail@email.com") >=0; });

如果您知道 firstemail@email.com 在数组中重复次数最少,则此方法有效,但这不是解决方案,因为我不知道哪个电子邮件重复次数最少.. 可能 Math.min 可以以某种方式使用,但我会很高兴得到帮助。

编辑:请看一下这段代码

var arr= new Array("10 firstemail@email.com","15 secondemail@email.com","25 secondemail@email.com","35 secondemail@email.com","15 firstemail@email.com"); // huge array with many emails not just 2

function extractEmails (text) { return text.match(/([a-zA-Z0-9._-]+@[a-zA-Z0-9._-]+\.[a-zA-Z0-9._-]+)/gi); } // Please edit the regEx to get least repeated email instead all

var get_least_repeated=extractEmails(arr.toString());

new_arr = $(arr).filter(function (str) { return arr[str].indexOf(get_least_repeated) >=0; });

console.log(new_arr);

这似乎效果最好,但我根本不擅长 regEx 来更改 extractEmails 函数以获取最少重复的电子邮件(目前得到所有)

另一个想法是以某种方式使用 jQuery.grep()。

编辑 2:我想出了我自己的优化代码,以 @arielb 的想法将电子邮件作为键和重复计数作为值的对象。

最终代码

var arr = new Array(
  "15 secondemail@email.com",
  "10 firstemail@email.com",
  "25 secondemail@email.com",
  "35 secondemail@email.com",
  "15 firstemail@email.com",
 "12 third@email.com",
 "35 secondemail@email.com"
); // huge array with many emails nut just 2


    var new_emails={}; //init an object
$.each(arr,function(k,v){
  var justmail=v.split(" ")[1];
  if(typeof(new_emails[justmail])=='undefined') new_emails[justmail]=0;
  new_emails[justmail]+=1; 
  });

var selectedemail=''; var eminvalue=Number.MAX_VALUE;
$.each(new_emails,function(k,v){
if(v<eminvalue) {eminvalue=v;selectedemail=k;}
});

var new_arr=$(arr).filter(function (str) { return arr[str].indexOf(selectedemail) >=0; });

console.log(new_arr);

【问题讨论】:

  • 不使用正则表达式来匹配电子邮件(已知有问题),为什么不匹配字符串开头的一些数字和一些空格(更容易匹配^\d+\s+)?您也可以只使用map:arr = arr.map(text =&gt; text.replace(/^\d+\s+/, '')),这将为您提供一系列电子邮件。然后,我将使用reduce 来完成其余部分。
  • @HereticMonkey 关于正则表达式的好点。这只是一个例子。问题是我相信正则表达式足够强大,可以计算重复次数并选择重复次数最少的那个,并避免数组上的循环。也不要忘记有 IE8 限制不支持原生 .map
  • 嗯,mapreduce 有 polyfills。我也会质疑 IE8 的正则表达式功能。请注意,Microsoft 不再支持 IE8,因此应该就该浏览器进行一些严肃的安全讨论...

标签: javascript jquery arrays filtering


【解决方案1】:

选项 1

var arr= new Array(
  "10 firstemail@email.com",
  "15 secondemail@email.com",
  "25 secondemail@email.com",
  "35 secondemail@email.com",
  "15 firstemail@email.com"); // huge array with many emails nut just 2

// Collect each unique email with its count
// and an array of each occurrence of the email
// in the original array
var emails = {};
$.each(arr, function(index, str) {
  var email = str.split(' ')[1];
  if (!emails[email]) {
    emails[email] = {values: [], count: 0}
  }
  emails[email].values.push(str);
  emails[email].count++;
});

var emailCounts = [];
// Create an array with unique emails and their counts
$.each(emails, function(email, data) {
  emailCounts.push([email, data.count])
})

// Sort the unique emails by count
emailCounts.sort(function(a, b) {
    return a[1] - b[1];
});

// First element in the sorted array is the least frequent
var leastFrequentEmail = emailCounts[0][0];

console.log(emails[leastFrequentEmail].values)

https://jsbin.com/milemugota/edit?js,console

它在整个数组上迭代一次,然后在唯一数组上迭代两次(一次用于收集计数,一次用于排序)。

选项 2

遵循https://www.sneppets.com/java/find-least-common-element-in-unsorted-array/的算法1

function emailPart(str) {
  return str.split(' ')[1];
}

var arr = new Array(
  "10 firstemail@email.com",
  "15 secondemail@email.com",
  "25 secondemail@email.com",
  "35 secondemail@email.com",
  "15 firstemail@email.com"); // huge array with many emails nut just 2

// sort by email
arr.sort(function(a, b) {
  var emailA = emailPart(a);
  var emailB = emailPart(b)
  if (emailA > emailB) {
    return 1;
  } else if (emailA < emailB) {
    return -1;
  } else {
    return 0;
  }
})

var currentEmailCount = 1;
var minEmailCount = arr.length + 1;
var leastCommonEmail = emailPart(arr[0]);

for (var i = 1; i < arr.length; i++) {
  if (emailPart(arr[i]) == emailPart(arr[i - 1])) {
    currentEmailCount++;
  } else {
    if (currentEmailCount < minEmailCount) {
      minEmailCount = currentEmailCount;
      leastCommonEmail = emailPart(arr[i - 1])
    }
    currentEmailCount = 1;
  }
}

if (currentEmailCount < minEmailCount) {
  leastCommonEmail = emailPart(arr[arr.length - 1]);
}

console.log(leastCommonEmail)

https://jsbin.com/gitacoqipa/edit?js,console

【讨论】:

  • 感谢您的回答!这可行,但更简洁和更快的解决方案将是(我认为):在 arr 实际上是数组之前 - 它是字符串。也许我们可以正则表达式该字符串非常好并获得最少重复的电子邮件?您可以使用 extractEmails(arr.toString()) ------ function extractEmails (text) { return text.match(/([a-zA-Z0-9._-]+@[a-zA-Z0 -9._-]+\.[a-zA-Z0-9._-]+)/gi);所以这将返回所有的电子邮件.. 如果只是最少重复一个呢?然后我将它与提到的过滤功能一起使用。
  • 我想不出一种方法来完成它只用一个正则表达式来返回最少出现的电子邮件
  • 也感谢选项 2。如果没有人提出正则表达式的想法或更快的想法,我想我会将您标记为解决方案,因为数组确实很大,并且操作越少越好。
【解决方案2】:

我会使用一个对象\字典来计算每封电子邮件的出现次数,而不需要任何过滤器。 也许是这样的:

    function check(arr){
    var emails={}; //init an object
    for(var i=0;i<arr.length;i++){
     emails[arr[i]]=++emails[arr[i]] || 1;
    }
    //now we are going to check which email is the least.
    var arrOccurences = [];
    var minValue = arr.length;
    var selectedEmail = '';
    jQuery.each(emails,function(key,value){
     if(value<minValue){
       selectedEmail=key;
       minValue = value;
    }

    });
    console.log(selectedEmail);
  }

【讨论】:

  • 2 个 fors 和 1 个 .. 数组很大,所以这缺乏性能。还是谢谢你。
  • 每个都在电子邮件字典上,它只会遍历唯一的电子邮件。大 0 仍然是 O(N)
  • @Svetoslav 我已经删除了一个,现在整个数组只有一个,而另一个 forEach 仅用于唯一的电子邮件地址,因此它明显小于 N。
猜你喜欢
  • 1970-01-01
  • 2011-01-10
  • 2020-08-15
  • 2019-12-27
  • 1970-01-01
  • 2020-10-05
  • 2012-12-06
  • 1970-01-01
  • 2018-09-16
相关资源
最近更新 更多