объедините 2 последовательности Linq в одну с приоритетом

Haskell использует стратегию реализации, известную как «стирание типов»: типы не имеют вычислительного значения, поэтому код, который вы генерируете, не должен их отслеживать. Это значительное преимущество для производительности.

Цена, которую вы платите за это преимущество в производительности, заключается в том, что типы не имеют вычислительной значимости: функция не может изменить свое поведение в зависимости от типа аргумента, который ей передан. Если бы вы допустили что-то вроде

f () = "foo"
f [] = "bar"

, то это свойство не было бы истинным: поведение f действительно зависело бы от типа его первого аргумента.

Конечно, есть языки, которые допускают подобные вещи, особенно в языках с типизированной зависимостью, где типы вообще не могут быть стерты.

1
задан JoelFan 17 June 2009 в 21:04
поделиться

2 ответа

Я бы начал с

var res = seq1.Union(seq2, Comparer);

, но документация для Enumerable.Union не указывает, из какой последовательности взят соответствующий элемент, и требует Comparer должен быть реализацией IEqualityComparer , которого у вас не будет, если TSource является анонимным типом (но, возможно, стоит конкретизировать, чтобы разрешить это).

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

IEnumerable<KeyValuePair<TKey, TValue>> Union(
                     this IEnumerable<KeyValuePair<TKey, TValue>> first,
                     IEnumerable<KeyValuePair<TKey, TValue>> second) {
   var allFirst = first.ToDictionary(v => v.Key, v => v.Value);
   foreach (var kv in allFirst) { yield return kv; }

   foreach (var s in second) {
     if (!allFirst.ContainsKey(s.Key)) {
       yield return s;
     }
 }

(Если вы хотите придерживаться своего собственного типа (свойства x и y), вы можете сделать этот универсальный параметр для одного параметра типа, но вам нужно будет добавить ограничение типа для предоставления доступа к отдельным свойствам.)

1
ответ дан 3 September 2019 в 01:23
поделиться

Возможно, вам будет проще сделайте это без Linq, но я думаю примерно так:

var distinctWithPrecedence = seq1
  .Concat(seq2)
  .GroupBy(i => i.x)
  .Select(g => g.First());

Если Linq не так уж много делает из-за своих укрытий. Основная идея - группировка по ключу. Затем пройдите по группам, вытягивая по первому элементу из каждой. Если Linq ведет себя так, как я думаю, первым элементом будет первый элемент из объединенного списка, что означает, что первая последовательность имеет прецедент.

Возможно, есть другие способы сделать это, но это первое, что пришло в голову.

1
ответ дан 3 September 2019 в 01:23
поделиться
Другие вопросы по тегам:

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