C# 交错电子邮件地址数组,避免具有相同域的项目连续

C# 交错电子邮件地址数组,避免具有相同域的项目连续,c#,arrays,algorithm,sorting,email-address,C#,Arrays,Algorithm,Sorting,Email Address,我正在寻找一种有效的方法对电子邮件地址数组进行排序,以避免具有相同域的项目在C#中连续出现 阵列中的电子邮件地址已经不同,并且都是小写的 例如: 给定包含以下项的数组: john.doe@domain1.com jane_doe@domain1.com patricksmith@domain2.com erick.brown@domain3.com 我想获得与以下类似的信息: john.doe@domain1.com patricksmith@domain2.com jane_doe@

我正在寻找一种有效的方法对电子邮件地址数组进行排序,以避免具有相同域的项目在C#中连续出现

阵列中的电子邮件地址已经不同,并且都是小写的

例如:

给定包含以下项的数组:

john.doe@domain1.com
jane_doe@domain1.com
patricksmith@domain2.com
erick.brown@domain3.com
我想获得与以下类似的信息:

john.doe@domain1.com    
patricksmith@domain2.com
jane_doe@domain1.com
erick.brown@domain3.com

我在这里要做的是首先对它们进行排序。 然后我从另一端重新安排。我相信有更有效的方法可以做到这一点,但这是一个简单的方法

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace ConsoleApplication4
{
    class Program
    {
        static void Main(string[] args)
        {
            String[] emails = { "john.doe@domain1.com", "jane_doe@domain1.com", "patricksmith@domain2.com", "erick.brown@domain3.com" };
            var result = process(emails);
        }

        static String[] process(String[] emails)
        {
            String[] result = new String[emails.Length];
            var comparer = new DomainComparer();
            Array.Sort(emails, comparer);
            for (int i = 0, j = emails.Length - 1, k = 0; i < j; i++, j--, k += 2)
            {
                if (i == j)
                    result[k] = emails[i];
                else
                {
                    result[k] = emails[i];
                    result[k + 1] = emails[j];
                }
            }

            return result;
        }
    }

    public class DomainComparer : IComparer<string>
    {
        public int Compare(string left, string right)
        {
            int at_pos = left.IndexOf('@');
            var left_domain = left.Substring(at_pos, left.Length - at_pos);
            at_pos = right.IndexOf('@');
            var right_domain = right.Substring(at_pos, right.Length - at_pos);
            return String.Compare(left_domain, right_domain);
        }
    }
}
使用系统;
使用System.Collections.Generic;
使用System.Linq;
使用系统文本;
命名空间控制台应用程序4
{
班级计划
{
静态void Main(字符串[]参数)
{
字符串[]电子邮件={“john”。doe@domain1.com简_doe@domain1.com", "patricksmith@domain2.com埃里克。brown@domain3.com" };
var结果=过程(电子邮件);
}
静态字符串[]进程(字符串[]电子邮件)
{
字符串[]结果=新字符串[emails.Length];
var comparer=new DomainComparer();
排序(电子邮件、比较器);
对于(inti=0,j=email.Length-1,k=0;i
类似的内容会将它们平均分布,但在新列表的末尾会出现问题(=连续元素)

        var list = new List<string>();
        list.Add("john.doe@domain1.com");
        list.Add("jane_doe@domain1.com");
        list.Add("patricksmith@domain2.com");
        list.Add("erick.brown@domain3.com");

        var x = list.GroupBy(content => content.Split('@')[1]);

        var newlist = new List<string>();
        bool addedSomething=true;
        int i = 0;
        while (addedSomething) {
            addedSomething = false;
            foreach (var grp in x) {
                if (grp.Count() > i) {
                    newlist.Add(grp.ElementAt(i));
                    addedSomething = true;
                }
            }
            i++;
        }
var list=newlist();
列表。添加(“john。doe@domain1.com");
列表。添加(“jane_doe@domain1.com");
列表。添加(“patricksmith@domain2.com");
列表。添加(“erick。brown@domain3.com");
var x=list.GroupBy(content=>content.Split('@')[1]);
var newlist=新列表();
bool addedSomething=真;
int i=0;
while(添加了一些内容){
addedSomething=false;
foreach(x中的var grp){
如果(grp.Count()>i){
新增(grp.ElementAt(i));
addedSomething=true;
}
}
i++;
}

这将使它们半均匀地分布,并试图避免彼此相邻的匹配域(尽管在某些列表中这可能是不可能的)。这个答案将使用OOP和Linq

使用系统;
使用System.Linq;
使用System.Collections.Generic;
公共课程
{
公共静态void Main()
{
var seed=新列表()
{
"1@a.com",
"2@a.com",
"3@a.com",
"4@a.com",
"5@a.com",
"6@a.com",
"7@a.com",
"8@a.com",
"9@a.com",
"10@a.com",
"1@b.com",
"2@b.com",
"3@b.com",
"1@c.com",
"4@b.com",
"2@c.com",
"3@c.com",
"4@c.com"
};
变量工作=种子
//创建EmailAddress对象的列表
.Select(s=>newemailaddress))//s.ToLowerCase()?
//按域对列表进行分组
.GroupBy(s=>s.Domain)
//创建一个列表
.选择(g=>new EmailAddressGroup(g))
.ToList();
var currentDomain=string.Empty;
而(work.Count>0)
{
//此列表不应与我们刚才使用的域相同
var noDups=work.Where(w=>w.Domain!=currentDomain);
//如果不存在,我们就完成了,否则就无法解决
if(noDups.Count()==0)
{
打破
}
//查找项目最多的第一组
var workGroup=noDups.First(w=>w.Count()==noDups.Max(g=>g.Count());
//获取电子邮件地址并将其从组列表中删除
var workItem=workGroup.Remove();
//如果组为空,请将其从*工作中删除*
if(workGroup.Count()==0)
{
工作。移除(工作组);
Console.WriteLine(“删除:“+workGroup.Domain”);
}
Console.WriteLine(workItem.FullEmail);
//上次查看的域。
currentDomain=工作项域;
}
Console.WriteLine(“无法有效分散电子邮件地址,剩余:”);
foreach(工作中的var工作组)
{
while(workGroup.Count()>0)
{
var item=workGroup.Remove();
Console.WriteLine(item.FullEmail);
}
}
}
公共类电子邮件地址
{
公共电子邮件地址(字符串电子邮件地址)
{
//附加电子邮件地址验证
var result=emailAddress.Split(新字符[]{'@},StringSplitOptions.RemoveEmptyEntries)
.ToList();
如果(result.Count()!=2)
{
新的例外情况(“电子邮件地址”);
}
this.FullEmail=电子邮件地址;
this.Name=结果[0];
this.Domain=结果[1];
}
using System;
using System.Linq;
using System.Collections.Generic;
                    
public class Program
{
    public static void Main()
    {
        var seed = new List<string>()
        {
            "1@a.com",
            "2@a.com",
            "3@a.com",
            "4@a.com",
            "5@a.com",
            "6@a.com",
            "7@a.com",
            "8@a.com",
            "9@a.com",
            "10@a.com",
            
            "1@b.com",
            "2@b.com",
            "3@b.com",

            "1@c.com",
            "4@b.com",
            "2@c.com",
            "3@c.com",
            "4@c.com"
        };
        
        var work = seed
            // Create a list of EmailAddress objects
            .Select(s => new EmailAddress(s)) // s.ToLowerCase() ?
            // Group the list by Domain
            .GroupBy(s => s.Domain)
            // Create a List<EmailAddressGroup>
            .Select(g => new EmailAddressGroup(g))
            .ToList();
        
        var currentDomain = string.Empty;
        while(work.Count > 0)
        {
            // this list should not be the same domain we just used
            var noDups = work.Where(w => w.Domain != currentDomain);
            // if none exist we are done, or it can't be solved
            if (noDups.Count() == 0)
            {
                break;
            }
            // find the first group with the most items
            var workGroup = noDups.First(w => w.Count() == noDups.Max(g => g.Count()));
            // get the email address and remove it from the group list
            var workItem = workGroup.Remove();
            
            // if the group is empty remove it from *work*
            if (workGroup.Count() == 0)
            {
                work.Remove(workGroup);
                Console.WriteLine("removed: " + workGroup.Domain);
            }
            
            Console.WriteLine(workItem.FullEmail);
            
            // last domain looked at.
            currentDomain = workItem.Domain;
        }
        
        Console.WriteLine("Cannot disperse email addresses affectively, left overs:");
        
        foreach(var workGroup in work)
        {
            while(workGroup.Count() > 0)
            {
                var item = workGroup.Remove();
                Console.WriteLine(item.FullEmail);
            }
        }
            
            
    }
    
    public class EmailAddress
    {
        public EmailAddress(string emailAddress)
        {
            // Additional Email Address Validation
            
            var result = emailAddress.Split(new char[] {'@'}, StringSplitOptions.RemoveEmptyEntries)
                .ToList();
            
            if (result.Count() != 2)
            {
                new ArgumentException("emailAddress");
            }
            
            this.FullEmail = emailAddress;
            this.Name = result[0];
            this.Domain = result[1];
        }
        
        public string Name { get; private set; }
        public string Domain { get; private set; }
        public string FullEmail { get; private set; }
    }
    
    public class EmailAddressGroup
    {
        private List<EmailAddress> _emails;
        
        public EmailAddressGroup(IEnumerable<EmailAddress> emails)
        {
            this._emails = emails.ToList();
            this.Domain = emails.First().Domain;
        }
        
        public int Count()
        {
            return _emails.Count();
        }
        
        public string Domain { get; private set; }
        
        public EmailAddress Remove()
        {
            var result = _emails.First();
            _emails.Remove(result);
            return result;
        }
    }
}
private IEnumerable<string> GetNonConsecutiveEmails(List<string> list)
{
    var emailAddresses = list.Distinct().Select(email => new EmailAddress { Email = email, Domain = email.Split('@')[1]}).ToArray();
    var groups = emailAddresses
                .GroupBy(addr => addr.Domain)
                .Select (group => new { Domain = group.Key, EmailAddresses = new Stack<EmailAddress>(group)})
                .ToList();

    EmailAddress lastEmail = null;
    while(groups.Any(g => g.EmailAddresses.Any()))
    {
        // Try and pick from the largest stack.
        var stack = groups
            .Where(g => (g.EmailAddresses.Any()) && (lastEmail == null ? true : lastEmail.Domain != g.Domain))
            .MaxBy(g => g.EmailAddresses.Count);

        // Null check to account for only 1 stack being left.
        // If so, pop the elements off the remaining stack.   
        lastEmail = (stack ?? groups.First(g => g.EmailAddresses.Any())).EmailAddresses.Pop();
        yield return lastEmail.Email;
    }
}

class EmailAddress
{
    public string Domain;
    public string Email;
}

public static class Extensions
{
    public static T MaxBy<T,U>(this IEnumerable<T> data, Func<T,U> f) where U:IComparable
    {
        return data.Aggregate((i1, i2) => f(i1).CompareTo(f(i2))>0 ? i1 : i2);
    }
}
List<string> emails = new List<string>();
emails.Add("john.doe@domain1.com");
emails.Add("jane_doe@domain1.com");
emails.Add("patricksmith@domain2.com");
emails.Add("erick.brown@domain3.com");

var q = emails.GroupBy(m => m.Split('@')[1]).Select(g => new List<string>(g)).Interleave();
public static IEnumerable<T> Interleave<T>(this IEnumerable<IEnumerable<T>> source )
{
    var queues = source.Select(x => new Queue<T>(x)).ToList();
    while (queues.Any(x => x.Any())) {
        foreach (var queue in queues.Where(x => x.Any())) {
            yield return queue.Dequeue();
        }
    }
}