Можно ли создать простой 'EqualityComparer <T>' с помощью лямбда-выражения

Я думаю, что вы ищете.

^.*?\d.(.*?)(journorequests\.com){1}

Это вернет контент, который вам нужен в первой группе захвата.

Смотрите мои работы здесь.

Также вы можете почитать Регулярные выражения, захват групп

.

39
задан Cœur 22 August 2017 в 14:58
поделиться

7 ответов

(Существует два решения здесь - посмотрите конец для второго):

Библиотека My MiscUtil имеет a ProjectionEqualityComparer класс (и два класса поддержки для использования вывода типа).

Вот пример использования его:

EqualityComparer<GalleryImage> comparer = 
    ProjectionEqualityComparer<GalleryImage>.Create(x => x.id);

Вот код (удаленные комментарии)

// Helper class for construction
public static class ProjectionEqualityComparer
{
    public static ProjectionEqualityComparer<TSource, TKey>
        Create<TSource, TKey>(Func<TSource, TKey> projection)
    {
        return new ProjectionEqualityComparer<TSource, TKey>(projection);
    }

    public static ProjectionEqualityComparer<TSource, TKey>
        Create<TSource, TKey> (TSource ignored,
                               Func<TSource, TKey> projection)
    {
        return new ProjectionEqualityComparer<TSource, TKey>(projection);
    }
}

public static class ProjectionEqualityComparer<TSource>
{
    public static ProjectionEqualityComparer<TSource, TKey>
        Create<TKey>(Func<TSource, TKey> projection)
    {
        return new ProjectionEqualityComparer<TSource, TKey>(projection);
    }
}

public class ProjectionEqualityComparer<TSource, TKey>
    : IEqualityComparer<TSource>
{
    readonly Func<TSource, TKey> projection;
    readonly IEqualityComparer<TKey> comparer;

    public ProjectionEqualityComparer(Func<TSource, TKey> projection)
        : this(projection, null)
    {
    }

    public ProjectionEqualityComparer(
        Func<TSource, TKey> projection,
        IEqualityComparer<TKey> comparer)
    {
        projection.ThrowIfNull("projection");
        this.comparer = comparer ?? EqualityComparer<TKey>.Default;
        this.projection = projection;
    }

    public bool Equals(TSource x, TSource y)
    {
        if (x == null && y == null)
        {
            return true;
        }
        if (x == null || y == null)
        {
            return false;
        }
        return comparer.Equals(projection(x), projection(y));
    }

    public int GetHashCode(TSource obj)
    {
        if (obj == null)
        {
            throw new ArgumentNullException("obj");
        }
        return comparer.GetHashCode(projection(obj));
    }
}

Второе решение

Чтобы сделать это только для Отличного, можно использовать DistinctBy расширение в MoreLINQ:

    public static IEnumerable<TSource> DistinctBy<TSource, TKey>
        (this IEnumerable<TSource> source,
         Func<TSource, TKey> keySelector)
    {
        return source.DistinctBy(keySelector, null);
    }

    public static IEnumerable<TSource> DistinctBy<TSource, TKey>
        (this IEnumerable<TSource> source,
         Func<TSource, TKey> keySelector,
         IEqualityComparer<TKey> comparer)
    {
        source.ThrowIfNull("source");
        keySelector.ThrowIfNull("keySelector");
        return DistinctByImpl(source, keySelector, comparer);
    }

    private static IEnumerable<TSource> DistinctByImpl<TSource, TKey>
        (IEnumerable<TSource> source,
         Func<TSource, TKey> keySelector,
         IEqualityComparer<TKey> comparer)
    {
        HashSet<TKey> knownKeys = new HashSet<TKey>(comparer);
        foreach (TSource element in source)
        {
            if (knownKeys.Add(keySelector(element)))
            {
                yield return element;
            }
        }
    }

В обоих случаях, ThrowIfNull похож на это:

public static void ThrowIfNull<T>(this T data, string name) where T : class
{
    if (data == null)
    {
        throw new ArgumentNullException(name);
    }
}
38
ответ дан Jon Skeet 27 November 2019 в 02:46
поделиться

Основываясь на ответе Charlie Flowers, можно создать собственный дополнительный метод, чтобы сделать то, что Вы хотите, который внутренне использует группировку:

    public static IEnumerable<T> Distinct<T, U>(
        this IEnumerable<T> seq, Func<T, U> getKey)
    {
        return
            from item in seq
            group item by getKey(item) into gp
            select gp.First();
    }

Вы могли также создать универсальный класс, происходящий из EqualityComparer, но он кажется, что требуется избежать этого:

    public class KeyEqualityComparer<T,U> : IEqualityComparer<T>
    {
        private Func<T,U> GetKey { get; set; }

        public KeyEqualityComparer(Func<T,U> getKey) {
            GetKey = getKey;
        }

        public bool Equals(T x, T y)
        {
            return GetKey(x).Equals(GetKey(y));
        }

        public int GetHashCode(T obj)
        {
            return GetKey(obj).GetHashCode();
        }
    }
6
ответ дан kvb 27 November 2019 в 02:46
поделиться

Это является лучшим, я могу придумать для проблемы в руке. Все еще любопытный, существует ли хороший способ создать a EqualityComparer на лету все же.

Galleries.SelectMany(x => x.Images).ToLookup(x => x.id).Select(x => x.First());

Создайте справочную таблицу и возьмите 'вершину' от каждого

Примечание: это совпадает с предложенным @charlie, но использующий ILookup - то, которое я думаю, - то, чем группа должна быть так или иначе.

3
ответ дан Simon_Weaver 27 November 2019 в 02:46
поделиться

Вы могли сгруппироваться значением ключа и затем выбрать главный объект из каждой группы. Это работало бы на Вас?

3
ответ дан Charlie Flowers 27 November 2019 в 02:46
поделиться

Вот интересная статья, которая расширяет LINQ с этой целью... http://www.singingeels.com/Articles/Extending_LINQ__Specifying_a_Property_in_the_Distinct_Function.aspx

Отличное значение по умолчанию сравнивает объекты на основе их хэш-кода - чтобы легко заставить Ваши объекты работать с Отличным, Вы могли переопределить метод GetHashcode.. но Вы упомянули получение объектов от веб-сервиса таким образом, Вы не можете делать это в этом случае.

1
ответ дан markt 27 November 2019 в 02:46
поделиться

Что относительно броска далеко IEqualityComparer универсальный класс?

public class ThrowAwayEqualityComparer<T> : IEqualityComparer<T>
{
  Func<T, T, bool> comparer;

  public ThrowAwayEqualityComparer(Func<T, T, bool> comparer)   
  {
    this.comparer = comparer;
  }

  public bool Equals(T a, T b)
  {
    return comparer(a, b);
  }

  public int GetHashCode(T a)
  {
    return a.GetHashCode();
  }
}

Таким образом, теперь можно использовать Distinct с пользовательским компаратором.

var distinctImages = allImages.Distinct(
   new ThrowAwayEqualityComparer<GalleryImage>((a, b) => a.Key == b.Key));

Вы смогли сходить с рук <GalleryImage>, но я не уверен, мог ли компилятор вывести тип (не имейте доступа к нему прямо сейчас.)

И в дополнительном дополнительном методе:

public static class IEnumerableExtensions
{
  public static IEnumerable<TValue> Distinct<TValue>(this IEnumerable<TValue> @this, Func<TValue, TValue, bool> comparer)
  {
    return @this.Distinct(new ThrowAwayEqualityComparer<TValue>(comparer);
  }

  private class ThrowAwayEqualityComparer...
}
1
ответ дан Jurriaan Pijpers 27 November 2019 в 02:46
поделиться

реализуйте IEquatable на GalleryImage, потому что он сгенерирован

Другой подход должен был бы генерировать GalleryImage как частичный класс и затем иметь другой файл с наследованием и IEquatable, Равняется, реализация GetHash.

0
ответ дан Richard 27 November 2019 в 02:46
поделиться
Другие вопросы по тегам:

Похожие вопросы: