简体   繁体   English

LINQ:选择一个系列?

[英]LINQ: Select a collection?

I'm trying to use LINQ: 我正在尝试使用LINQ:

IEnumerable<String> debtors = (from expense in CurrentExpenses
                               where expense.WhoPaid == username
                               select expense.WhoOwes.AsEnumerable()).Distinct();

( username and WhoPaid are strings, WhoOwes is ICollection<String> ) usernameWhoPaid是字符串, WhoOwesICollection<String>

What I want to do is get an IEnumerable of, for each expense where username paid, all the people who owe for it. 我想要做的是获得一个IEnumerable ,对于每个expense username费用,所有欠它的人。 I'm not really sure how to do it. 我不太确定该怎么做。 Here is the compiler error: 这是编译器错误:

Cannot implicitly convert type 'System.Collections.Generic.IEnumerable<System.Collections.Generic.IEnumerable<string>>' to 'System.Collections.Generic.IEnumerable<string>'. An explicit conversion exists (are you missing a cast?)

What is the correct syntax for this? 这个的正确语法是什么?

The code you've provided doesn't compile because you're trying to assign a sequence of a sequence of strings (each top-level sequence coming from a specific expense) to a reference that expects a sequence of strings. 您提供的代码无法编译,因为您尝试将一系列字符串序列(每个顶级序列来自特定费用)分配给需要字符串序列的引用。

Going by the return-type of your query, I assume you only need a sequence containing all the debtors for the user? 按照查询的返回类型,我假设您只需要一个包含用户所有债务人的序列? If so, you need to flatten the result sequence. 如果是这样,您需要展平结果序列。

// implicitly IEnumerable<string>
var debtors = CurrentExpenses.Where(expense => expense.WhoPaid == username)
                             .Select(expense => expense.WhoOwes)
                             .SelectMany(debtors => debtors) // flatten sequence
                             .Distinct();

(you can use a single SelectMany clause to do the projection and flattening together.) (您可以使用单个SelectMany子句进行投影和展平。)

or, in query syntax: 或者,在查询语法中:

var debtors = (from expense in CurrentExpenses
               where expense.WhoPaid == username
               from debtor in expense.WhoOwes
               select debtor).Distinct();

If you need to find all expenses paid by the user and their associated debtors, you can stop at the first filter: 如果您需要查找用户及其相关债务人支付的所有费用,您可以在第一个过滤器处停止:

// implicitly IEnumerable<Expense>
var expensesPaidByUser = CurrentExpenses.Where(expense => expense.WhoPaid == username);

The debtors associated with each expense are already encapsulated in the Expense object, so you probably don't need a query more complicated than this; 与每笔费用相关联的债务人已经封装在Expense对象中,因此您可能不需要比这更复杂的查询; it's already effectively a sequence of a sequence of debtors grouped by expense. 它已经实际上是按费用分组的一系列债务人序列。

If you do want a separate type to hold an expense and its associated debtors, you can do this with an anonymous type, although I don't see why its necessary in your case: 如果你想要一个单独的类型来支付费用及其相关的债务人,你可以用匿名类型来做,虽然我不明白为什么在你的情况下它是必要的:

// implictly IEnumerable<anonymousType>
var debtorsByExpense = CurrentExpenses.Where(expense => expense.WhoPaid == username)
                                      .Select(expense => new { Expense = expense, Debtors = expense.WhoOwes });

Use: 采用:

var debtors = ...

instead of 代替

IEnumerable<String> debtors = ...

The return type of LINQ expressions is often difficult to determine for the programmer. LINQ表达式的返回类型通常很难为程序员确定。 The var keyword tells the compiler to infer the type automatically, so you don't need to. var关键字告诉编译器自动推断类型,因此您不需要。 Hover your mouse cursor over var in your IDE to see what the compiler has inferred. 将鼠标光标悬停在IDE中的var ,以查看编译器推断出的内容。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM