57

これはばかげているように見えるかもしれませんが、linqで使用するために私が見つけたすべての例では、Except文字列または整数のみの2つのリストまたは配列を使用し、一致に基づいてそれらをフィルタリングします。次に例を示します。

var excludes = users.Except(matches);

コードを短くシンプルに保つためにexcludeを使用したいのですが、次の方法を見つけることができないようです。

class AppMeta
{
    public int Id { get; set; }
}

var excludedAppIds = new List<int> {2, 3, 5, 6};
var unfilteredApps = new List<AppMeta>
                         {
                           new AppMeta {Id = 1},
                           new AppMeta {Id = 2},
                           new AppMeta {Id = 3},
                           new AppMeta {Id = 4},
                           new AppMeta {Id = 5}
                         }

AppMetaフィルタを適用するバックのリストを取得するにはどうすればよいexcludedAppIdsですか?

4

8 に答える 8

100

簡単な where クエリを試す

var filtered = unfilteredApps.Where(i => !excludedAppIds.Contains(i.Id)); 

except メソッドは等価性を使用します。リストには異なるタイプのオブジェクトが含まれているため、それらに含まれるアイテムはどれも等しくありません!

于 2013-03-21T06:33:46.773 に答える
18

ColinE の答えはシンプルかつエレガントです。リストが大きく、除外されたアプリのリストが並べ替えられている場合、 はBinarySearch<T>よりも高速になることがありContainsます。

例:

unfilteredApps.Where(i => excludedAppIds.BinarySearch(i.Id) < 0);
于 2013-03-21T06:39:30.457 に答える
15

私は、Except の拡張メソッドを使用します。これにより、ID やキーなど、比較に使用できる共通のものが両方にある限り、Apple と Orange を比較できます。

public static class ExtensionMethods
{
    public static IEnumerable<TA> Except<TA, TB, TK>(
        this IEnumerable<TA> a,
        IEnumerable<TB> b,
        Func<TA, TK> selectKeyA,
        Func<TB, TK> selectKeyB, 
        IEqualityComparer<TK> comparer = null)
    {
        return a.Where(aItem => !b.Select(bItem => selectKeyB(bItem)).Contains(selectKeyA(aItem), comparer));
    }
}

次に、次のように使用します。

var filteredApps = unfilteredApps.Except(excludedAppIds, a => a.Id, b => b);

拡張機能は ColinE の回答と非常によく似ています。精神的なオーバーヘッドをあまりかけずに再利用できるきちんとした拡張機能にパッケージ化されているだけです。

于 2014-03-04T00:29:12.773 に答える
13

これがLINQに必要なものです

public static IEnumerable<T> Except<T, TKey>(this IEnumerable<T> items, IEnumerable<T> other, Func<T, TKey> getKey) 
{
    return from item in items
            join otherItem in other on getKey(item)
            equals getKey(otherItem) into tempItems
            from temp in tempItems.DefaultIfEmpty()
            where ReferenceEquals(null, temp) || temp.Equals(default(T))
            select item; 
}
于 2015-04-17T12:14:29.783 に答える
8

List<AppMeta>除外されたリストからa を構築し、Except Linq 演算子を使用します。

var ex = excludedAppIds.Select(x => new AppMeta{Id = x}).ToList();                           
var result = ex.Except(unfilteredApps).ToList();
于 2013-03-21T06:36:56.287 に答える
1

私はExcept拡張メソッドが好きですが、元の質問には対称キーアクセスがなく、Contains(またはAnyバリエーション)が参加することを好むので、azunecaの回答にすべての功績があります:

public static IEnumerable<T> Except<T, TKey>(this IEnumerable<TKey> items,
    IEnumerable<T> other, Func<T, TKey> getKey) {

    return from item in items
        where !other.Contains(getKey(item))
        select item;
}

これは次のように使用できます。

var filteredApps = unfilteredApps.Except(excludedAppIds, ua => ua.Id);

また、このバージョンでは、Select を使用して例外 IEnumerable のマッピングを必要とすることができます。

var filteredApps = unfilteredApps.Except(excludedApps.Select(a => a.Id), ua => ua.Id);
于 2016-11-01T23:30:59.240 に答える