簡體   English   中英

C#-通過將第二個數據表與第三個數據表進行比較,從一個數據表復制行

[英]C# - Copy rows from one DataTable by comparing with 2nd DataTable to 3rd DataTable

我的C#代碼中有4個DataTables

DataTable dt1;
DataTable dt2;
DataTable dt3;
DataTable dt4;

dt1有以下記錄

Id | Name | City
----------------
1 | Abc | Khi
2 | XYZ | Hyd
3 | TVW | Lhr
4 | tyz | Isb

dt2只有ID記錄

Id
---
2
4

我需要復制僅從行dt1它們也可用dt2dt3 還需要將不匹配的記錄存儲在第四dt4

我發現這一點,但不知道如何復制到datatable正確,以及如何not equals在這里工作

var matchingRows = from s1 in dt1.AsEnumerable()
                               join s2 in d2.AsEnumerable() on s1.Field<int>("Id") equals s2.Field<int>("Id")
                               select s1;

我不喜歡在不需要時使用var。 您正在失去對實際操作的跟蹤。 mathcingRows是一個列表。 因此任務很簡單:

           List<DataRow> matchingRows = (from s1 in dt1.AsEnumerable()
                                          join s2 in dt2.AsEnumerable() on s1.Field<int>("Id") equals s2.Field<int>("Id")
                                          select s1).ToList();
            foreach (DataRow row in matchingRows)
            {
                dt4.Rows.Add(row);
            }

您可以創建兩個查詢來查找匹配和不匹配的行,然后將這些行復制到每個答案DataTable

var dt3 = dt1.Clone();
var dt4 = dt1.Clone();

var matchingRows = from s1 in dt1.AsEnumerable()
                   join s2 in dt2.AsEnumerable() on s1.Field<int>("Id") equals s2.Field<int>("Id")
                   select s1;

matchingRows.CopyToDataTable(dt3, LoadOption.OverwriteChanges);

var nonMatchingRows = from s1 in dt1.AsEnumerable()
                      where !dt2.AsEnumerable().Any(s2 => s2.Field<int>("Id") == s1.Field<int>("Id"))
                      select s1;

nonMatchingRows.CopyToDataTable(dt4, LoadOption.OverwriteChanges);

如果dt2具有大量條目,並且性能比內存更重要,則可以將dt2轉換為HashSet來優化匹配測試:

var dt2hs = new HashSet<int>(dt2.AsEnumerable().Select(r => r.Field<int>("Id")));

var matchingRows = from s1 in dt1.AsEnumerable()
                   where dt2hs.Contains(s1.Field<int>("Id"))
                   select s1;

var nonMatchingRows = from s1 in dt1.AsEnumerable()
                      where !dt2hs.Contains(s1.Field<int>("Id"))
                      select s1;

另一個性能選擇是僅掃描dt1一次,然后手動循環並選擇每個目標:

var dt1jdt2 = from s1 in dt1.AsEnumerable()
              join s2 in dt2.AsEnumerable() on s1.Field<int>("Id") equals s2.Field<int>("Id") into s2j
              from s2 in s2j.DefaultIfEmpty()
              select new { s1, s2 };

foreach (var r in dt1jdt2) {
    if (r.s2 != null)
        dt3.Rows.Add(r.s1.ItemArray);
    else
        dt4.Rows.Add(r.s1.ItemArray);
}

當然,您可以結合使用HashSet和單個掃描選項:

var dt2hs = new HashSet<int>(dt2.AsEnumerable().Select(r => r.Field<int>("Id")));

foreach (var s1 in dt1.AsEnumerable())
    if (dt2hs.Contains(s1.Field<int>("Id")))
        dt3.Rows.Add(s1.ItemArray);
    else
        dt4.Rows.Add(s1.ItemArray);

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM