【问题标题】:Linq query where first column from DataTable is compared to second column for duplicatesLinq 查询,其中 DataTable 的第一列与重复的第二列进行比较
【发布时间】:2020-09-09 12:39:33
【问题描述】:

我已合并在两列中都包含重复项的 DataTable。

DataTable 结构:“Worknumber 用户名”

1234 John
1235 Mike
1235 Mike
1236 Donald
1236 Jack

我要赶上

1236 Donald
1236 Jack

最好以格式输出

1236 Donald Jack

我一直在尝试为此目的创建 Linq 查询一段时间(相当长的时间),但我无法找到正确的方法。

这是我目前所拥有的。这行得通,我刚刚用dataRow.Field<string>("WORKNUMBER") 测试了列名是否正确:

        public static DataTable ProjectsInLiinos = new DataTable();

        ...

        MainProcess.MergedTable();

        foreach (DataRow dataRow in MainProcess.ProjectsInLiinos.Rows)
        {
                Console.WriteLine(dataRow.Field<string>("WORKNUMBER") + dataRow.Field<string>("USERNAME"));
        }

这是 Linq 查询:

var queryCustomers = from data in MainProcess.ProjectsInLiinos.AsEnumerable()
                                 where data.Field<string>("WORKNUMBER").Count() > 1 && data.Field<string>("USERNAME").Count() < 1
                                 select data;

它不会产生任何东西。我不知道如何将第一列重复项与第二列重复项进行比较?

否则我可以将 dataRow.Field&lt;string&gt;("WORKNUMBER") + dataRow.Field&lt;string&gt;("USERNAME") 分组,然后检查列表是否有重复项,但它会生成:

1235Mike
1235Mike

反过来

1234John
1236Donald
1236Jack

【问题讨论】:

  • 通常在这种情况下,您会按重复列分组。然后你会得到这个分组键的所有值,就像你想要的输出一样
  • 你想要怎样的输出?在匿名类型中?自定义类?

标签: c# linq


【解决方案1】:

尝试以下:

            DataTable dt = new DataTable();
            dt.Columns.Add("Worknumber",typeof(int));
            dt.Columns.Add("Username",typeof(string));
            
            dt.Rows.Add(new object[] {1234, "John"});
            dt.Rows.Add(new object[] {1235, "Mike"});
            dt.Rows.Add(new object[] {1235, "Mike"});
            dt.Rows.Add(new object[] {1236, "Donald"});
            dt.Rows.Add(new object[] {1236, "Jack"});

            var distinct = dt.AsEnumerable()
                .GroupBy(x => x.Field<int>("Worknumber"))
                .Select(x => new { workNumber = x.Key, user = x.Select(y => y.Field<string>("Username")).Distinct().ToList() })
                .Where(x => x.user.Count > 1)
                .Select(x => new { workNumber = x.workNumber, user = string.Join(" ", x.user) })
                .ToList();

【讨论】:

    【解决方案2】:

    查看这个简单的演示

    public class C
    {
        public int Worknumber { get; set; }
        public string Username { get; set; }
    
        public C(int worknumber, string username)
        {
            Worknumber = worknumber;
            Username = username;
        }
    }
    
    void Main()
    {
        var lst = new List<C>(){
            new C(1234, "Mike"),
            new C(1235, "Mike"),
            new C(1235, "Mike"),
            new C(1236, "Donald"),
            new C(1236, "Jake")
        };
    
        var p = lst.GroupBy(t => t.Worknumber)
            .Select(t => new { Key = t.Key, l = t.Select(x => x.Username).ToList() })
            .Where(x => x.l.Distinct().Count() > 1)
            .Select(x => String.Format("{0} {1}", x.Key,  string.Join(' ', x.l)))
            .Dump();
    }
    

    【讨论】:

      【解决方案3】:

      您可以使用分组方式:

      void Main()
      {
          DataTable tbl = new DataTable();
          tbl.Columns.Add("Id", typeof(int));
          tbl.Columns.Add("Name", typeof(string));
          tbl.Rows.Add(1234, "John");
          tbl.Rows.Add(1235, "Mike");
          tbl.Rows.Add(1235, "Mike");
          tbl.Rows.Add(1236, "Donald");
          tbl.Rows.Add(1236, "Jack");
      
          var dupes = tbl.AsEnumerable()
          .GroupBy(t => t.Field<int>("Id"))
          .Where(x => x.Select(y => y.Field<string>("Name")).Distinct().Count() > 1)
          .Select(x => new
          {
              Id = x.Key,
              Names = string.Join(",", x.Select(y => y.Field<string>("Name")))
          });
          foreach (var dupe in dupes)
          {
              Console.WriteLine($"{dupe.Id}:{dupe.Names}");
          }
      }
      

      我认为无论如何使用源代码会好得多,而不是介于两者之间的 DataTable。

      【讨论】:

        【解决方案4】:

        正如已经建议的那样,首先使用第一列分组。然后,您可以通过 Where 过滤器中的第二个分组找到不同的用户名:

        void Main()
        {
            string column1 = "Worknumber";
            string column2 = "Username";
            DataTable table = new DataTable();
            table.Columns.Add(column1, typeof(int));
            table.Columns.Add(column2, typeof(string));
        
            table.Rows.Add(1234, "john");
            table.Rows.Add(1235, "Mike");
            table.Rows.Add(1235, "Mike");
            table.Rows.Add(1236, "Donald");
            table.Rows.Add(1236, "Jack");
            table.Rows.Add(1237, "Val");
            table.Rows.Add(1237, "Nick");
            var result = table.AsEnumerable()
                 .GroupBy(x => x.Field<int>(column1))
                 .Where(g => g.Count() > 1 && g.GroupBy(x => x.Field<string>(column2)).Count() > 1)
                 .Select(x => new {WorkNumber = x.Key, AllUsers = string.Join(" ", x.Select(u => u.Field<string>(column2)))}).Dump();       
        
        }
        

        我在这里使用了匿名类型,但您可以轻松编写自定义类,并使用适当的构造函数来适应用户名值。

        【讨论】:

          【解决方案5】:

          假设你有

          class MyClass : IEquatable<MyClass> // IEquatable is required to perform Dictinct()
          {
              public string Worknumber { get; set; }
              public string Username { get; set; }
          
              public bool Equals(MyClass other)
              {
                  if (this.Username != other.Username)
                      return false;
          
                  if (this.Worknumber != other.Worknumber)
                      return false;
          
                  return true;
              }
          
              public override int GetHashCode() // required for objects comparison
              {
                  int hashWorknumber = Worknumber == null ? 0 : Worknumber.GetHashCode();
                  int hashUsername = Username == null ? 0 : Username.GetHashCode();
          
                  return hashWorknumber ^ hashUsername;
              }
          }
          

          还有这样的模拟

          List<MyClass> myclasses = new List<MyClass>();
          
          myclasses.Add(new MyClass { Worknumber = "1234", Username = "John" });
          myclasses.Add(new MyClass { Worknumber = "1235", Username = "Mike" });
          myclasses.Add(new MyClass { Worknumber = "1235", Username = "Mike" });
          myclasses.Add(new MyClass { Worknumber = "1236", Username = "Donald" });
          myclasses.Add(new MyClass { Worknumber = "1236", Username = "Jack" });
          

          我们做一个简单的 lambda 查询

          var result = myclasses
              .Distinct()
              .GroupBy(e => e.Worknumber) // grouping
              .Select(e => new
              {
                  Worknumber = e.Key,
                  Count = e.Count(),
                  Users = string.Join(" ", e.Select(p => p.Username)) // joining names
              })
              .Where(e => e.Count > 1) // filtering duplicates only
              .ToList();
          

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 1970-01-01
            • 2022-10-06
            • 1970-01-01
            • 1970-01-01
            • 2019-11-27
            • 2022-01-16
            • 1970-01-01
            • 2019-11-14
            相关资源
            最近更新 更多