0

データベースに 2 つのフィールドを持つテーブルがあります: index (int), email( varchar(100) )

次のことを行う必要があります。

  1. すべての電子メールをドメイン名でグループ化します (すべての電子メールは既に小文字になっています)。
  2. ステップ 1 の前に、ドメインの電子メールの合計が総電子メールの 20% を超えていないすべてのグループからすべての電子メールを選択します。

コード例:

    DataContext db = new DataContext();

    //Domains to group by
    List<string> domains = new List<string>() { "gmail.com", "yahoo.com", "hotmail.com" };

    Dictionary<string, List<string>> emailGroups = new Dictionary<string, List<string>>();

    //Init dictionary
    foreach (string thisDomain in domains)
    {
        emailGroups.Add(thisDomain, new List<string>());
    }

    //Get distinct emails
    var emails = db.Clients.Select(x => x.Email).Distinct();

    //Total emails
    int totalEmails = emails.Count();

    //One percent of total emails
    int onePercent = totalEmails / 100;

    //Run on each email
    foreach (var thisEmail in emails)
    {
        //Run on each domain
        foreach (string thisDomain in emailGroups.Keys)
        {
            //If email from this domain
            if (thisEmail.Contains(thisDomain))
            {
                //Add to dictionary
                emailGroups[thisDomain].Add(thisEmail);
            }
        }
    }

    //Will store the final result
    List<string> finalEmails = new List<string>();

    //Run on each domain
    foreach (string thisDomain in emailGroups.Keys)
    {
        //Get percent of emails in group
        int thisDomainPercents = emailGroups[thisDomain].Count / onePercent;

        //More than 20%
        if (thisDomainPercents > 20)
        {
            //Take only 20% and join to the final result
            finalEmails = finalEmails.Union(emailGroups[thisDomain].Take(20 * onePercent)).ToList();
        }
        else
        {
            //Join all to the final result
            finalEmails = finalEmails.Union(emailGroups[thisDomain]).ToList();
        }
    }

誰かがそれを作るためのより良い方法を知っていますか?

4

3 に答える 3

1

各グループの最後の項目を昇順で取得するとします。

int m = (int) (input.Count() * 0.2);
var result = input.GroupBy(x=>x.email.Split('@')[1],
                          (key,g)=>g.OrderByDescending(x=>x.index).Take(m)
                                    .OrderBy(x=>x.index))
                  .SelectMany(g=>g);//If you want to get the last result without grouping

またはこれ:

var result = input.GroupBy(x=>x.email.Split('@')[1],
                          (key,g)=>g.OrderBy(x=>x.index)
                                    .Skip(g.Count()-m))
                  .SelectMany(g=>g);//If you want to get the last result without grouping
于 2013-10-01T14:29:39.663 に答える