使用LINQ比较两个列表

时间:2011-05-11 20:50:13

标签: asp.net linq linq-to-objects

如果我有2个字符串列表:

List<string> firstList = new List<string>("010", "111", "123");
List<string> secondList = new List<string>("010", "111", "999");

如何比较列表中每个项目中的每个字符?例如:应将“0”与“0”,“1”与“1”,“0”与“0”进行比较,依此类推。似乎我可以使用SelectMany,但我仍然坚持如何做到这一点

编辑:

这些列表在相互比较时应该返回true(因为星号表示任何字符,我正在验证以确保每个项目的长度恰好为3个字符)

List<string> firstList = new List<string>("010", "111", "123");
List<string> secondList = new List<string>("010", "1*1", "***");

3 个答案:

答案 0 :(得分:5)

更新了通配符

class WildcardStringComparer : IEqualityComparer<string>
{
    public bool Equals(string s1, string s2)
    {
        if (s1.Length != s2.Length) return false;

        for (int i = 0; i < s1.Length; i++)
        {
            if (s1[i] != s2[i] && s1[i] != '*' && s2[i] != '*')
                return false;
        }

        return true;
    }


    public int GetHashCode(string obj)
    {
        throw new NotImplementedException();
    }
}

结果:

List<string> firstList = new List<string>{"010", "111", "999"};
List<string> secondList = new List<string>{"010", "111", "999"};

bool res = firstList.SequenceEqual(secondList, new WildcardStringComparer()); // True

List<string> firstList = new List<string>{"010", "111", "999"};
List<string> secondList = new List<string>{"010", "111", "*99"};

bool res = firstList.SequenceEqual(secondList, new WildcardStringComparer()); // True

List<string> firstList = new List<string>{"010", "111", "999"};
List<string> secondList = new List<string>{"010", "111", "199"};

bool res = firstList.SequenceEqual(secondList, new WildcardStringComparer()); // False

答案 1 :(得分:1)

如果您只想比较列表中匹配的字符序列:

bool sameCharacters = Enumerable.SequenceEqual(firstList.SelectMany(x => x), 
                                               secondList.SelectMany(x => x));

这将导致true,即对于以下两个列表 - 它们的字符序列匹配(两者都为"010111123"),它们各自的字符串条目不匹配:

List<string> firstList = new List<string> {"010", "111", "123" };
List<string> secondList = new List<string> {"010", "11", "1123" };

根据评论进行修改:

对于通配符匹配,您可以使用Zip()并比较每个字符,如果它们根据通配符条件匹配则返回true,然后检查压缩序列中的每个元素是否为true

var isWildCardMatch = firstList.SelectMany(x =&gt; x).Zip(secondList.SelectMany(x =&gt; x),                                               (a,b)=&gt;         {             if(a == b || a ==''|| b =='')                 返回true;             return false;

    }).All( x=> x);

上面的方法越过了字符串入口边界,这会导致错误的匹配 - 这里有一个更好的方法:

bool isWildCardMatch = firstList.Zip(secondList, (x, y) =>
{
    var matchWord = y.Select((c, i) => c == '*' ? x[i] : c);
    return matchWord.SequenceEqual(x);
}).All(x => x);

答案 2 :(得分:0)

假设您要将第一个列表中第一个字符串的第一个字符与第二个列表中第一个字符串的第一个字符进行比较,将第一个字符串中第一个字符串的第二个字符与第一个字符串的第二个字符进行比较我可以想到两个实现。

我要开始的那个:

var firstCharList = new List<char>();
var secondCharList = new List<char>();

firstList.foreach(s => 
 {
   foreach(char c in s)
   {
      firstCharList.Add(c);
   }
  });

secondList.foreach(s =>
{
   foreach(char c in s)
   {
      secondCharList.Add(c);
   }
});

for(int i = 0; i < firstCharList.Length; i++)
{
   if(firstCharList[i] == secondCharList[i]) yield return i;
}

这将生成一个列表(或数组,或其他)的int对应于两个字符串具有相同字符的索引。

第二个是:

firstList.foreach(s =>
{
   var index = firstList.IndexOf(s);
   var sPrime = secondList[index];
   for(int i = 0; i < s.Length; i++)
   {
      if(s[i] == sPrime[i]) yield return s[i];
   }
}

那个只返回在相同索引处相同的任何字符。