0

私はこれに対する答えを見つけるためにインターネット全体を検索しました。ネストされた for ループを使用して 2 つのリスト (list1 と list2) をループし、3 つの基準に基づいて最初のリストの重複レコードを削除しています。これら 2 つのリストのすべてのレコードが互いに一致する場合、範囲外エラーが発生します。最初のリストからすべてのアイテムを削除し、最終的に0に減少し、ループするレコードがなく、ifステートメントを配置して最初のリストの数を確認すると発生すると思います(if inbox_emails_filtered_contacts. Count > 0) も役に立ちません。このエラーが発生する理由を教えていただける方がいらっしゃいましたら、お知らせください。

C#.net の Outlook アドイン

for (int i = 0; i < list1.Count; i++)
{
    for (int j = 0; j < list2.Count; j++)
    {
        if (list1.Count > 0)
        {
            if ((list1[i].username == registered_user)
                && (list1[i].from_email.ToLower() == list2[j].from_email.ToLower())
                && (list1[i].email_subject == list2[j].email_subject)
                && (list1[i].email_timestamp.ToLongDateString() == list2[j].email_timestamp.ToLongDateString()))
            {
                //Remove the duplicate email from inbox_emails_filtered_contacts
                list1.RemoveAt(i);
            }
        }
    }
}
4

4 に答える 4

1

whileここでループを使用することをお勧めします。また、最初からチェックを再開するには、一致が見つかった場合は内部ループを抜け出す必要があります。

int i = 0;
while (i < list1.Count)
{
    int found = 0;
    for (int j = 0; j < list2.Count; j++)
    {
        if ((list1[i].username == registered_user)
            && (list1[i].from_email.ToLower() == list2[j].from_email.ToLower())
            && (list1[i].email_subject == list2[j].email_subject)
            && (list1[i].email_timestamp.ToLongDateString() == list2[j].email_timestamp.ToLongDateString()))
        {
            //Remove the duplicate email from inbox_emails_filtered_contacts
            list1.RemoveAt(i);
            found = 1;
            break;
        }
   }
   if (!found)
   {
       i++;
   }
}
于 2012-07-20T07:51:54.477 に答える
0

これは Email クラスの実装です

class Email:IComparable<Email>
{
    private static int _Id;

    public Email()
    {
        Id = _Id++;
    }

    public int Id { get; private set; }
    public string UserName { get; set; }
    public string Body { get; set; }
    public string Subject { get; set; }
    public DateTime TimeStamp { get; set; }

    public override int GetHashCode()
    {
        return UserName.GetHashCode() ^ Body.GetHashCode() ^ Subject.GetHashCode();
    }

    public int CompareTo(Email other)
    {
        return GetHashCode().CompareTo(other.GetHashCode());
    }

    public override string ToString()
    {
        return String.Format("ID:{0} - {1}", Id, Subject);
    }

    public override bool Equals(object obj)
    {
        if (obj is Email)
            return CompareTo(obj as Email) == 0;
        return false;
    }

}

差分を取得する2つの方法。

        var list1 = new List<Email>();
        var ran = new Random();
        for (int i = 0; i < 50; i++)
        {
            list1.Add(new Email() { Body = "Body " + i, Subject = "Subject " + i, UserName = "username " + i, TimeStamp = DateTime.UtcNow.AddMinutes(ran.Next(-360, 60)) });
        }
        var list2 =  new List<Email>();

        for (int i = 0; i < 50; i++)
        {
            if (i % 2 == 0)
                list2.Add(new Email() { Body = "Body " + i, Subject = "Subject Modifed" + i, UserName = "username " + i, TimeStamp = DateTime.UtcNow.AddMinutes(ran.Next(-360, 60)) });
            else 
                list2.Add(new Email() { Body = "Body " + i, Subject = "Subject " + i, UserName = "username " + i, TimeStamp = DateTime.UtcNow.AddMinutes(ran.Next(-360, 60)) });

        }


        foreach (var item in list2.Intersect<Email>(list1))
        {
            Console.WriteLine(item);
        }

        foreach (var item in list1)
        {
            for (int i = 0; i < list2.Count; i++)
            {

                if (list2[i].Equals(item))
                {
                    Console.WriteLine(item);
                    list2.RemoveAt(i);
                    break;
                }
            }
        }

        Console.WriteLine(list2.Count);
于 2012-07-20T10:04:31.170 に答える
0

おそらく、application_emails に複数の重複があるため、removeAt(i) が複数回呼び出されています。あなたの if は、 i が 2 より長いリストの最後の項目であり、複数回削除することになるケースを決してキャッチしません。

さらに、remove ステートメントを使用してメールをスキップすることにもなります。i=4 と仮定すると、4 インデックス 4 で削除すると、新しいアイテムが含まれ、次の反復で i は 5 になります。while ループを使ったほうがいいかもしれません

int i=0;
while (i < inbox_emails.Count) {
   bool foundDuplicate=false;
   for (int j=0;j<for (int j = 0; j < application_emails.Count; j++) {       
     if ((inbox_emails[i].username == registered_user)       
         && (inbox_emails[i].from_email.ToLower() == application_emails[j].from_email.ToLower())       
         && (inbox_emails[i].email_subject == application_emails[j].email_subject)       
         && (inbox_emails[i].email_timestamp.ToLongDateString() == application[j].email_timestamp.ToLongDateString()))       
        {       
           foundDuplicate=true;
           break;   // This is optional but it stops the j loop from continuing as we've found a duplicate
        }       
    }   
    if (foundDuplicate) {
       inbox_emails.RemoveAt(i);
    } else {
       i++;
    }
}

これが単一のスレッドである場合は、Linq を使用してリストを置き換えることができます。using System.Linq

inbox_emails = inbox_emails.Where(i=> 
                 i.username != registered_user 
                 || ! application_emails.Any(j=>
                    i.from_email.ToLower() == j.from_email.ToLower()
                    && i.email_subject == j.email_subject
                    && i.email_timestamp.ToLongDateString() == j.email_timestamp.ToLongDateString()
                    )
                 ).ToList();
于 2012-07-20T07:50:38.680 に答える
0

リスト/配列から項目を削除しながら反復する場合は、逆を使用します (Visual のスニペット「forr」)。

for (int i = list1.Count - 1; i >= 0; i--)
于 2012-07-20T07:43:03.733 に答える