Инвертирование contains
От: Аноним  
Дата: 06.10.10 06:32
Оценка:
Есть на linq функция Contains.

Получаю в качестве параметра массив элементов.
Иногда надо вывести только элементы, которые в массиве, а иногда наоборот надо их "выбросить".
Ввел параметр Exclude — bool
Как это сделать без написания if а с помощью contains?
Re: Инвертирование contains
От: QrystaL Украина  
Дата: 06.10.10 06:53
Оценка:
Сформулируйте задачу более внятно. Какая сигнатура желаемого метода?
Re[2]: Инвертирование contains
От: Аноним  
Дата: 06.10.10 06:58
Оценка:
Здравствуйте, QrystaL, Вы писали:

QL>Сформулируйте задачу более внятно. Какая сигнатура желаемого метода?



bool b = false;

nodes.Where(n => new int[] {1, 2, 3}.Contains(n.Count));



хочется не писать


if (b)
  nodes.Where(n => new int[] {1, 2, 3}.Contains(n.Count));
else 
  nodes.Where(n => !new int[] {1, 2, 3}.Contains(n.Count));


а один раз написать contains
Re[3]: Инвертирование contains
От: anton_t Россия  
Дата: 06.10.10 07:01
Оценка:
Здравствуйте, Аноним, Вы писали:

А>а один раз написать contains


nodes.Where(n => new int[] {1, 2, 3}.Contains(n.Count) == b)
Re[3]: Инвертирование contains
От: _FRED_ Черногория
Дата: 06.10.10 07:03
Оценка:
Здравствуйте, Аноним, Вы писали:

QL>>Сформулируйте задачу более внятно. Какая сигнатура желаемого метода?

А>bool b = false;

А>nodes.Where(n => new int[] {1, 2, 3}.Contains(n.Count));

А>хочется не писать
А>if (b)
А>  nodes.Where(n => new int[] {1, 2, 3}.Contains(n.Count));
А>else 
А>  nodes.Where(n => !new int[] {1, 2, 3}.Contains(n.Count));

А>а один раз написать contains

Здесь вы на ровном (линейном) месте получаете квадратичную производительность
Help will always be given at Hogwarts to those who ask for it.
Re: Инвертирование contains
От: _FRED_ Черногория
Дата: 06.10.10 07:18
Оценка: 7 (1)
Здравствуйте, Аноним, Вы писали:

А>Есть на linq функция Contains.

А>Получаю в качестве параметра массив элементов.
А>Иногда надо вывести только элементы, которые в массиве, а иногда наоборот надо их "выбросить".
А>Ввел параметр Exclude — bool
А>Как это сделать без написания if а с помощью contains?

// Определяем, есть ли один из элементов массива в nodes
var result = nodes.Intersect(new int[] {1, 2, 3}).Any();

Теперь у нас есть булев параметр exclude, который должен работать так:

exclude→
result

true
false
true
false
true
false
true
false
var exclude = false; // То есть, с учётом exclude:
var result = nodes.Intersect(new int[] {1, 2, 3}).Any() ^ exclude;
Help will always be given at Hogwarts to those who ask for it.
Re[4]: Инвертирование contains
От: _FRED_ Черногория
Дата: 06.10.10 07:19
Оценка:
Здравствуйте, _FRED_, Вы писали:

QL>>>Сформулируйте задачу более внятно. Какая сигнатура желаемого метода?

_FR>
А>>bool b = false;

А>>nodes.Where(n => new int[] {1, 2, 3}.Contains(n.Count));
_FR>


_FR>Здесь вы на ровном (линейном) месте получаете квадратичную производительность


Хотя нет, место не такое уж и ровное
Help will always be given at Hogwarts to those who ask for it.
Re[2]: Инвертирование contains
От: Sinix  
Дата: 06.10.10 10:30
Оценка:
Здравствуйте, _FRED_, Вы писали:

// Определяем, есть ли один из элементов массива в nodes
var result = nodes.Intersect(new int[] {1, 2, 3}).Any();

Не всегда подойдёт — Intersect и ко устраняет дубликаты
Re[3]: Инвертирование contains
От: _FRED_ Черногория
Дата: 06.10.10 10:35
Оценка:
Здравствуйте, Sinix, Вы писали:

S>// Определяем, есть ли один из элементов массива в nodes
S>var result = nodes.Intersect(new int[] {1, 2, 3}).Any();

S>Не всегда подойдёт — Intersect и ко устраняет дубликаты

Ну и что? Можно посмотреть на примеры конкретных данных и на то, что именно "Не подойдёт"?
Help will always be given at Hogwarts to those who ask for it.
Re[2]: Инвертирование contains
От: Lloyd Россия  
Дата: 06.10.10 10:40
Оценка:
Здравствуйте, _FRED_, Вы писали:

_FR>
_FR>// Определяем, есть ли один из элементов массива в nodes
_FR>var result = nodes.Intersect(new int[] {1, 2, 3}).Any();
_FR>

_FR>Теперь у нас есть булев параметр exclude, который должен работать так:

_FR>
_FR>var exclude = false; // То есть, с учётом exclude:
_FR>var result = nodes.Intersect(new int[] {1, 2, 3}).Any() ^ exclude;
_FR>


А где тут "вывести элементы"?
Re[4]: Инвертирование contains
От: Sinix  
Дата: 06.10.10 10:51
Оценка:
Здравствуйте, _FRED_, Вы писали:

_FR>Ну и что? Можно посмотреть на примеры конкретных данных и на то, что именно "Не подойдёт"?


Исходная задача:

Есть на linq функция Contains.

Получаю в качестве параметра массив элементов.
Иногда надо вывести только элементы, которые в массиве, а иногда наоборот надо их "выбросить".


// псевдокод.
int[] source = { 1, 1, 3, 2, 4, 2, 42 };
int[] filterItems={ 2, 34 };

var temp = exclude?
  source.Except(filterItems):
  source.intersect(filterItems);

var temp2 = exclude?
  source.Where(item => !filterItems.Contains(item)):
  source.Where(item => filterItems.Contains(item));

Re[3]: Инвертирование contains
От: _FRED_ Черногория
Дата: 06.10.10 10:58
Оценка: :)
Здравствуйте, Lloyd, Вы писали:

L>А где тут "вывести элементы"?


Да, я почему-то на другой, не заданный, вопрос ответил
Help will always be given at Hogwarts to those who ask for it.
Re[5]: Инвертирование contains
От: _FRED_ Черногория
Дата: 06.10.10 11:08
Оценка: +1
Здравствуйте, Sinix, Вы писали:

_FR>>Ну и что? Можно посмотреть на примеры конкретных данных и на то, что именно "Не подойдёт"?

S>Исходная задача:

S>Есть на linq функция Contains.

S>Получаю в качестве параметра массив элементов.
S>Иногда надо вывести только элементы, которые в массиве, а иногда наоборот надо их "выбросить".


Ага, я просто не правильно понял топикстартера и решал совсем другую задачу.

S>// псевдокод.
S>int[] source = { 1, 1, 3, 2, 4, 2, 42 };
S>int[] filterItems={ 2, 34 };

S>var temp = exclude?
S>  source.Except(filterItems):
S>  source.intersect(filterItems);

S>var temp2 = exclude?
S>  source.Where(item => !filterItems.Contains(item)):
S>  source.Where(item => filterItems.Contains(item));

S>

А "другую задачу" и нужно решать по-другому.
Help will always be given at Hogwarts to those who ask for it.
Re[4]: Инвертирование contains
От: Аноним  
Дата: 06.10.10 11:11
Оценка:
Здравствуйте, _FRED_, Вы писали:

_FR>Здравствуйте, Lloyd, Вы писали:


L>>А где тут "вывести элементы"?


_FR>Да, я почему-то на другой, не заданный, вопрос ответил


в общем, получается, не подоходит вариант с Intersect
Re: Инвертирование contains
От: Lloyd Россия  
Дата: 06.10.10 11:20
Оценка:
Здравствуйте, Аноним, Вы писали:

А>Как это сделать без написания if а с помощью contains?


nodes.Where(_ => toExclude.Contains(_) ^ flag);

Для toExclude лучше использовать HashSet, чтобы избежать упомянутой квадратичной зависимоси.
Re[5]: Инвертирование contains
От: _FRED_ Черногория
Дата: 06.10.10 11:26
Оценка:
Здравствуйте, Аноним, Вы писали:

L>>>А где тут "вывести элементы"?

_FR>>Да, я почему-то на другой, не заданный, вопрос ответил

А>в общем, получается, не подоходит вариант с Intersect


Главное в моём ответе (и, на самом деле в стартовом вопросе) — это не Intersect, а ксор. Вот вам элементы, а там уж или печатайте их или что ещё:
private static IEnumerable<T> Get<T>(this IEnumerable<T> source, IEnumerable<T> check, bool exclude, IEqualityComparer<T> comparer = null) {
  var set = new HashSet<T>(check, comparer);
  return source.Where(item => set.Contains(item) ^ exclude);
}
Help will always be given at Hogwarts to those who ask for it.
Re[2]: Инвертирование contains
От: Аноним  
Дата: 07.10.10 09:42
Оценка:
Здравствуйте, Lloyd, Вы писали:

L>Здравствуйте, Аноним, Вы писали:


А>>Как это сделать без написания if а с помощью contains?


L>
L>nodes.Where(_ => toExclude.Contains(_) ^ flag);
L>

L>Для toExclude лучше использовать HashSet, чтобы избежать упомянутой квадратичной зависимоси.

а где почитать про внутренности linq или как лучше писать на linq чтобы добиться оптимальной производительности?
Re[3]: Инвертирование contains
От: Lloyd Россия  
Дата: 07.10.10 17:34
Оценка:
Здравствуйте, Аноним, Вы писали:

L>>
L>>nodes.Where(_ => toExclude.Contains(_) ^ flag);
L>>

L>>Для toExclude лучше использовать HashSet, чтобы избежать упомянутой квадратичной зависимоси.

А>а где почитать про внутренности linq или как лучше писать на linq чтобы добиться оптимальной производительности?


Не знаю, что посоветовать. Тут главное понимать, во что разворачивается linq-овские вызовы и уже из этого строить предположения по поводу производительности.
Например, твой код развернется во что-то типа (на самом деле будут еще и вызовы с лямбдой, но это несущественно):
foreach(var n in nodes) {
  bool contains = false;
  foreach(var ex in new []{1, 2, 3}) {
    if (ex == n) {
      contains = true;
      break;
    }
  }

  if (contains)
    yield return n;
}


Тут явно заметны 2 косяка:
1. пересоздание массива на каждой итерации
2. линейный поиск по массиву.
Обе этих проблемы решаются заменой массива на HashSet и выносом за тело метода.
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.