根据2个条件选择使用linq

时间:2012-08-29 23:49:22

标签: c# linq collections

我有一个收藏品。我想选择符合2个条件的值。

var a;
var b;
foreach(SomeObject so in collection)
{
    if(so.Value == something) 
    {
        a = so;
        // break if b is not null.
    }
    else if(so.Value == somethingElse) 
    {
        b = so;
        // break if a is not null
    }
}

是否可以使用linq迭代仅对集合执行上述操作一次?如果我们可以使用这个事实,那么只有一个值的东西和一个值的东西。

6 个答案:

答案 0 :(得分:3)

此解决方案将列表缩小为两个元素,然后从那里开始。使用Take(2)因此只搜索集合,直到找到两个值。

var matches = collection.Where(x => x.Value == something || x.Value == somethingElse)
                        .Take(2)
                        .ToList();
var a = matches.Single(x => x.Value == something);
var b = matches.Single(x => x.Value == somethingElse);

答案 1 :(得分:2)

你需要这样的东西:

var a = collection.OfType<YourCollectionElementType>().FirstOrDefault(i=>i.Equals(something));
var b = collection.OfType<YourCollectionElementType>().FirstOrDefault(i=>i.Equals(somethingelse));

您的收藏集应至少实现IEnumerable以便能够使用此代码。 这取决于您的收藏类型。如果它实现了通用IEnumerable<T>,说它是List<YourCollectionElementType>或数组YourCollectionElementType[],那么您不需要使用OfType<T>,即

var a = collection.FirstOrDefault(i=>i.Equals(something));
var b = collection.FirstOrDefault(i=>i.Equals(somethingelse));

如果您的收藏集不包含该值,则a和/或b会获得null个值。

实际上你可以在MSDN中阅读所有这些内容。如果你尝试,LINQ并不难学 例如:

  1. Enumerable.FirstOrDefault Method (IEnumerable)

  2. Enumerable.OfType Method

  3. 修改

    在您的评论中,您说确保只有一个值。你需要两个独立的变量是非常重要的吗?你可以像这样获得现值:

    object thevalue = collection.FirstOrDefault(i => i == something || i == somethingelse);
    

    修改

    实际上,我会保留你的循环,只是添加了这样一行:

    SomeObject a;
    SomeObject b;
    foreach(SomeObject so in collection)
    {
        if(so.Value == something)
            a = so;
        else if(so.Value == somethingElse)
            b = so;
        if(a!=null && b!=null)
            break;
    }
    

    如果只有一个值,那么

    SomeObject a;
    SomeObject b;
    foreach(SomeObject so in collection)
    {
        if(so.Value == something)
        {
            a = so;
            break;
        }
        else if(so.Value == somethingElse)
        {
            b = so;
            break;
        }
    }
    

答案 2 :(得分:2)

var relevant =
  from so in l where so.Value == something || so.Value == somethingElse
  group so by so.Value == something into grp
  select new {ForA = grp.Key, SO = grp.First()};
foreach(var bit in relevant)
  if(bit.ForA)
    a = bit.SO;
  else
    b = bit.SO;

它可以获得一些针对某些来源的东西,因为只检索了两个项目,但是如果针对内存中的一个集合,我将保留你所拥有的,但添加一个catch以便一旦你设置了{{ 1}}和a,你停止循环而不是不必要地检查集合。

答案 3 :(得分:1)

你可以这样做:

collection
    .Select(x => x.Value == something
        ? () => a = x
        : (x.Value == somethingElse
            ? () => b = x 
            : (Action)null))
    .Where(x => x != null)
    .ToArray()
    .ForEach(x => x());

我测试了这段代码并且它有所作为。

如果集合在某个地方的某个数据库上,那么我建议:

collection
    .Where(x => x.Value == something || x.Value == somethingElse)
    .ToArray()
    .Select(x => x.Value == something
        ? () => a = x
        : (x.Value == somethingElse
            ? () => b = x 
            : (Action)null))
    .Where(x => x != null)
    .ToArray()
    .ForEach(x => x());

答案 4 :(得分:0)

当然可以,但我不推荐它。你现在已经拥有循环它会更清晰。

如果你真的想知道怎么做,你可以这样做:

class SomeObject
{
    public string Value { get; set; }
}
var items = new[]
{
    new SomeObject { Value = "foo" },
    new SomeObject { Value = "bar" },
    new SomeObject { Value = "baz" },
};

var something = "foo";
var somethingElse = "baz";
var result = items.Aggregate(
    Tuple.Create(default(SomeObject), default(SomeObject)),
    (acc, item) => Tuple.Create(
        item.Value == something     ? item : acc.Item1,
        item.Value == somethingElse ? item : acc.Item2
    )
);
// result.Item1 <- a == new SomeObject { Value = "foo" }
// result.Item2 <- b == new SomeObject { Value = "baz" }

答案 5 :(得分:0)

不确定如果我理解您的问题,但假设SomethingSomethingElse是值类型并且在运行时之前已知,则可以在下面的一个语句中执行以下操作。

        var FindItems = new[]
        {
            new SomeObject { Value = "SomethingElse" }
        };

        var CollectionItems = new[]
        {
            new SomeObject { Value = "Something" },
            new SomeObject { Value = "SomethingElse" }
        };

        var qSomeObject = CollectionItems
                          .Where(c => FindItems.Any(x => c.Value == x.Value));