3

コレクションがあります。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
    }
}

コレクションを1回だけ反復するlinqを使用して、上記を実行することはできますか?その事実を使用できる場合、何かの値とsomethingElseの値は1つだけになります。

4

6 に答える 6

3

このソリューションでは、リストを 2 つの要素に絞り込み、そこから先に進みます。 Take(2)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);
于 2012-08-30T02:04:28.873 に答える
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 メソッド (IEnumerable)

  2. Enumerable.OfType メソッド

編集

あなたのコメントでは、値が1つしか存在しないことが保証されていると言っています。2 つの個別の変数が必要であることは非常に重要ですか? 次のように現在価値を取得できます。

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;
}

そして、値の 1 つだけが期待される場合、

SomeObject a;
SomeObject b;
foreach(SomeObject so in collection)
{
    if(so.Value == something)
    {
        a = so;
        break;
    }
    else if(so.Value == somethingElse)
    {
        b = so;
        break;
    }
}
于 2012-08-30T00:21:18.040 に答える
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;

2つのアイテムしか取得されないという点で、いくつかのソースに対して何かを得ることができますが、メモリ内のコレクションに対して私はあなたが持っていたものにとどまりますが、両方aを設定するとbループが停止するようにキャッチを追加しますコレクションを不必要に調べ続けるのではなく。

于 2012-08-30T01:46:45.243 に答える
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());
于 2012-08-30T01:54:31.630 に答える
0

私があなたの質問を理解していても、値型であり、実行前に既知であると仮定するSomethingと、次のように 1 つのステートメントで実行できます。SomethingElse

        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));
于 2012-08-30T02:35:00.330 に答える
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" }
于 2012-08-30T01:20:34.157 に答える