1

我正在尝试构建一个 lambda 表达式,它将一个数组的元素与第二个数组匹配。以下是此查询的简化版本:

class Program
{
    static void Main(string[] args)
    {
        string[] listOne = new string[] { "test1", "test2", "test3" };
        MyClass[] listTwo = new MyClass[] { new MyClass("test1") };

        string[] newVals = listOne.Where(p => listTwo.Select(e => e.Name).Equals(p)).ToArray();

        //string[] newVals2 = listOne.Intersect(listTwo.Select(t => t.Name)).ToArray();
    }

    class MyClass
    {
        public MyClass(string name)
        {
            Name = name;
        }
        public string Name {get; set;}
    }
}

我希望newVals返回一个包含 1 个值的数组,但它是空的。我意识到取消注释 myVals2 将获得相同的结果,但类列表的根本差异比显示的要大。

4

5 回答 5

4

您正在使用Equals,但您应该使用Contains. 您正在检查IEnumerable<>是否等于p,但您想检查是否IEnumerable<>包含p,因此请替换:

string[] newVals = listOne.
                   Where(p => listTwo.Select(e => e.Name).Equals(p)).
                   ToArray();

string[] newVals = listOne.
                   Where(p => listTwo.Select(e => e.Name).Contains(p)).
                   ToArray();
于 2013-01-25T16:14:23.980 回答
2

您可能想对Join2 个集合执行 a 。

var q = 
  listOne
  .Join(
    listTwo,
    l2 => l2,
    l1 => l1.Name,
    (l2, l1) => new { l2, l1, });

您可以更改选择器(最后一个参数)以满足您的需要,如果它只是 listOne 中的值,例如然后 have (l2, l1) => l1

其他解决方案将起作用,但可能不像您期望的那样。

在 where 子句中使用 Linq-Objects Contains 将listTwo导致对.listOne

于 2013-01-25T16:19:18.727 回答
2

尝试这个:

string[] listOne = new string[] { "test1", "test2", "test3" };
        MyClass[] listTwo = new MyClass[] { new MyClass("test1") };

        string[] newVals = listOne
                       .Where(p => listTwo.Select(e => e.Name).Contains(p))
                       .ToArray();

listTwo.Select(e => e.Name)是一个IEnumerable<string>

于 2013-01-25T16:14:31.270 回答
1

像这样的东西怎么样:

string[] newVals = listOne.Where(p => listTwo.Any(e => e.Name.Contains(p))).ToArray();

或者更严格地使用==而不是Contains.

但是,如果您想获得两者之间共有的项目,为什么不直接调用.Intersect()??

于 2013-01-25T16:15:35.787 回答
0

您正在尝试执行联接,从技术上讲,您最好简化 linq 语句以使用联接。下面包括一个示例。

    static void Main(string[] args)
    {
        string[] listOne = new [] { "test1", "test2", "test3" };
        MyClass[] listTwo = new [] { new MyClass("test1") };

        string[] newVals = (from str1 in listOne
                           join str2 in  listTwo.Select(e => e.Name) on str1 equals str2
                           select str1).ToArray();
        foreach (var newVal in newVals)
        {
            Console.WriteLine(newVal);
        }

        //string[] newVals2 = listOne.Intersect(listTwo.Select(t => t.Name)).ToArray();
    }

    class MyClass
    {
        public MyClass(string name)
        {
            Name = name;
        }
        public string Name { get; set; }
    }
于 2013-01-25T16:21:14.107 回答