【问题标题】:Check if elements from one list elements present in another list检查一个列表元素中的元素是否存在于另一个列表中
【发布时间】:2022-01-06 08:20:49
【问题描述】:

我有 2 个 c# 类 -

class ABC
{
  string LogId;
  string Name;
}

class XYZ
{
  string LogId;
  string Name;
}

class Checker
{
  public void comparelists()
  {
    List<ABC> lstABC =new List<ABC>();
    lstABC.Add(new ABC...);
    lstABC.Add(new ABC...);
    lstABC.Add(new ABC...);

    List<XYZ> lstXYZ =new List<XYZ>();
    lstXYZ.Add(new XYZ...);
    lstXYZ.Add(new XYZ...);
    lstXYZ.Add(new XYZ...);

    var commonLogId = lstABC
      .Where(x => lstXYZ.All(y => y.LogId.Contains(x.LogId)))
      .ToList();


  }
}

从代码中可以看出,我想从 lstABC 中获取 lstXYZ 中存在的所有 logid。

例如。 lstABC 有 ->

LogId="1", Name="somename1"
LogId="2", Name="somename2"
LogId="3", Name="somename3"
LogId="4", Name="somename4"
LogId="5", Name="somename5"

lstXYZ 有 ->

LogId="1", Name="somename11"
LogId="2", Name="somename22"
LogId="3", Name="somename33"
LogId="8", Name="somename8"
LogId="9", Name="somename9"

然后 lstXYZ 中存在的 lstABC 中的所有 logid 都是 - 1,2,3 ;所以所有这些记录都应该被获取。

但使用以下 linq 查询 -

var commonLogId = lstABC
  .Where(x => lstXYZ.All(y => y.LogId.Contains(x.LogId)))
  .ToList();

正在获取/选择 0 条记录。

【问题讨论】:

    标签: c# linq .net-core


    【解决方案1】:

    通过Any()接近

    var res = lstABC.Where(x => (lstXYZ.Any(y => y.LogId == x.LogId))).Select(x => x.LogId);
    

    https://dotnetfiddle.net/jRnUwS


    另一种方法是Intersect(),这对我来说感觉更自然

    var res = lstABC.Select(x => x.LogId).Intersect(lstXYZ.Select(y => y.LogId));
    

    https://dotnetfiddle.net/7iWYDO

    【讨论】:

      【解决方案2】:

      您使用了错误的 LINQ 函数。试试Any()

      var commonLogId = lstABC
        .Where(x => lstXYZ.Any(y => y.LogId == x.LogId))
        .ToList();
      

      还要注意与Contains() 的id 比较是错误的。只需改用==

      All() 检查列表中的所有元素是否满足指定条件。另一方面,Any() 仅检查是否至少有一个元素存在。

      请注意,当两个列表都很大时,您的实现将非常缓慢,因为它的运行时复杂性随着要比较的元素数量呈二次方增长。更快的实现将使用专门为此目的创建和优化的Join()

      var commonLogIds = lstABC
        .Join(
           lstXYZ,
           x => x.LogId,  // Defines what to use as key in `lstABC`.
           y => y.LogId,  // Defines what to use as key in `lstXYZ`.
           (x, y) => x)   // Defines the output of matched pairs. Here
                          // we simply use the values of `lstABC`.
        .ToList();
      

      【讨论】:

        【解决方案3】:

        与完全不同的类型相交似乎很不自然,所以我很想连接共性并写一个EqualityComparer

        class ABC : ILogIdProvider
        {
            public string LogId {get;set;}
            public string Name;
        }
        
        class XYZ : ILogIdProvider
        {
            public string LogId{get;set;}
            public string Name;
        }
        
        interface ILogIdProvider
        {
            string LogId{get;}
        }
        
        class LogIdComparer : EqualityComparer<ILogIdProvider>
        {
            public override int GetHashCode(ILogIdProvider obj) => obj.LogId.GetHashCode();
            
            public override bool Equals(ILogIdProvider x, ILogIdProvider y) => x.LogId == y.LogId;
        }
        

        那么你可以更自然地Intersect列表:

        var res = lstABC.Intersect(lstXYZ, new LogIdComparer());
        

        现场示例:https://dotnetfiddle.net/0Tt6eu

        【讨论】:

          猜你喜欢
          • 2021-08-24
          • 2012-08-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2022-01-08
          • 2020-07-07
          • 1970-01-01
          相关资源
          最近更新 更多