C# 在 ToDictionary() 方法中填充值字段的 Lambda 方法?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/905933/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Lambda way to fill the value field in the ToDictionary() method?
提问by Boris Callens
I have two IEnumerable
我有两个 IEnumerable
IEnumerable<MyObject> allowedObjects = MyService.GetAllowedObjects();
IEnumerable<MyOBject> preferedObjects = MyService.GetPreferedObjects();
We can safely assume that preferedObjects will always be a subset of allowedObjects.
I want to create an IDictionary<MyObject, bool>
. Objects where the key is the set of MyObjects from the allowedObjects and the bool is true if the MyObject instance was also in the preferedObjects enumerable.
我们可以安全地假设preferedObjects 将始终是allowedObjects 的子集。
我想创建一个IDictionary<MyObject, bool>
. 键是来自 allowedObjects 的 MyObjects 集的对象,如果 MyObject 实例也在可枚举的 preferredObjects 中,则 bool 为真。
I can do this by enumerating them and adding them one by one, but I would like to be able to do something like this:
我可以通过枚举它们并一一添加来做到这一点,但我希望能够做这样的事情:
IDictionary<MyObject, bool> selectedObjects = allowedObjects
.ToDictionary(o => new KeyValuePair<MyObject, bool>()
{ Key = q,
Value = preferedObjects.Any(q)
}
);
UPDATE
Exchanged Contains with Any;
The solution that is suggested most was what I tried first, but it isn't accepted for some reason:
UPDATE
Exchanged contains with Any; 建议最多的解决方案是我首先尝试的解决方案,但由于某种原因未被接受:
IDictionary<MyObject, bool> selectedObjects = allowedObjects
.ToDictionary<MyObject, bool>(o => o, preferedObjects.Any(o));
Visual studio says the first method does not return a bool. Which is true, but mainly because a bool would not be the correct result to start with...
And then it says it cannot infere the type of the second lambda...
As you can see I tried to explicitly define the types to help the inference, but it doesn't solve a thing..
Visual Studio 表示第一种方法不返回布尔值。这是真的,但主要是因为 bool 不是正确的结果......
然后它说它不能推断第二个 lambda 的类型......
正如你所看到的,我试图明确定义类型来帮助推论,但它不能解决任何问题..
Suggestions?
建议?
Disclaimer: names and code are snippyfied to keep the focus where it should be
免责声明:名称和代码被剪掉以将焦点保持在应有的位置
采纳答案by Matt Hamilton
I can't remember whether Linq provides a "Contains" extension method on IEnumerable<T>
. If not, you could use Any:
我不记得 Linq 是否在IEnumerable<T>
. 如果没有,您可以使用 Any:
var dict = allowedObjects.ToDictionary(o => o,
o => preferredObjects.Contains(o));
** Edit ** Yep, just tested it and there is indeed a Contains() extension method, so the above code works.
** 编辑 ** 是的,刚刚测试了一下,确实有一个 Contains() 扩展方法,所以上面的代码可以工作。
回答by Richard
Enumerable.ToDictionary
has multiple overloads. Some of these take a second delegate (so you can pass a lambda) to return the value to go with the key.
Enumerable.ToDictionary
有多个重载。其中一些需要第二个委托(因此您可以传递一个 lambda)来返回与键一起使用的值。
Something like:
就像是:
var secondDict = firstDictionary
.Where(p => SomeCondition(p))
.ToDictionary(p => p.Key, p => p.Value);
回答by Noldorin
You're almost there:
您快到了:
IDictionary<MyObject, bool> selectedObjects = allowedObjects
.ToDictionary(o => o, o => preferedObjects.Contains(q));
The ToDictionary
extension method works around using two lambda expressions to generate the key/value pair rather than the KeyValuePair
type.
该ToDictionary
扩展方法能解决使用两个lambda表达式生成密钥/值对,而不是KeyValuePair
类型。
You could speed things dramatically by using HashSet<T>
objects for your allowedObjects
and preferredObjects
collections, though I wouldn't bother unless your lists are especially large/performance is important.
您可以通过HashSet<T>
为您的allowedObjects
和preferredObjects
集合使用对象来显着加快处理速度,但除非您的列表特别大/性能很重要,否则我不会打扰。
回答by Frans Bouma
You can of course create your own extension method. ToDictionary simply creates a dictionary by adding all elements in the source as values and using a lambda as key. You can create your own with a different approach. As you use 'contains' I don't think it's a good idea to do it that way, as it is a slow operation (linear search, for every element in allowedObjects, you're enumerating preferredobjects).
您当然可以创建自己的扩展方法。ToDictionary 通过将源中的所有元素添加为值并使用 lambda 作为键来创建字典。您可以使用不同的方法创建自己的方法。当您使用“包含”时,我认为这样做不是一个好主意,因为它是一个缓慢的操作(线性搜索,对于 allowedObjects 中的每个元素,您正在枚举首选对象)。
One approach could be to add all preferredobjects to a HashSet and use Contains on that. Another could be to use a linq query where you join actualObjects with preferredObjects, using join into, and use DefaultIfEmpty. This is more efficient:
一种方法是将所有首选对象添加到 HashSet 并在其上使用 Contains。另一种可能是使用 linq 查询,在其中将实际对象与首选对象连接起来,使用 join into 并使用 DefaultIfEmpty。这是更有效的:
List<MyObject> allowedObjects = new List<MyObject>() { new MyObject("one"), new MyObject("two"), new MyObject("three")};
List<MyObject> preferredObjects = allowedObjects.Take(2).ToList();
var q = from a in allowedObjects
join p in preferredObjects on a equals p into ap
from x in ap.DefaultIfEmpty()
let isPreferred = (x != null)
let toUse = x ?? a
select new { toUse, isPreferred };
Dictionary<MyObject, bool> selectedObjects = new Dictionary<MyObject, bool>();
foreach(var v in q)
{
selectedObjects.Add(v.toUse, v.isPreferred);
Console.WriteLine("{0}, {1}", v.toUse.Foo, v.isPreferred);
}