Сделать из одного массива - два
От: snaphold  
Дата: 10.11.22 10:22
Оценка:
Есть такой массив.

List<Person> persons

Person
age
name

как из persons одним запросом через Linq получить 2 массива: ages (distinct age from persons), names (distinct name from persons) ?

то есть хотелось бы такого вида получить
(names, ages) = persons.SelectMany(x => (n, a), n.Distinct(name), a.Distinct(a.age));
Re: Сделать из одного массива - два
От: IT Россия linq2db.com
Дата: 10.11.22 16:16
Оценка:
Здравствуйте, snaphold, Вы писали:

S>как из persons одним запросом через Linq получить 2 массива: ages (distinct age from persons), names (distinct name from persons) ?


Пиши свой метод. Linq — это про другое.
Если нам не помогут, то мы тоже никого не пощадим.
Re: Сделать из одного массива - два
От: IT Россия linq2db.com
Дата: 10.11.22 16:28
Оценка: +2
Здравствуйте, snaphold, Вы писали:

S>как из persons одним запросом через Linq получить 2 массива: ages (distinct age from persons), names (distinct name from persons) ?


Впрочем, в качестве бреда:

var list = new List<(string name, int age)> { ("1", 2), ("3", 4) };

var data = list.Aggregate(
    (names : new HashSet<string>(), ages : new HashSet<int>()),
    (seed, item) =>
    {
        seed.names.Add(item.name);
        seed.ages. Add(item.age);
        return seed;
    });
Если нам не помогут, то мы тоже никого не пощадим.
Отредактировано 11.11.2022 14:39 IT . Предыдущая версия .
Re: Сделать из одного массива - два
От: Baiker  
Дата: 10.11.22 20:21
Оценка: +1 -1
Здравствуйте, snaphold, Вы писали:

S>как из persons одним запросом через Linq получить 2 массива: ages (distinct age from persons), names (distinct name from persons) ?


Никак, это задача не для одного запроса. Как вариант для одного ПРОХОДА — да, можно безо всяких LINQ тупо пройтись циклом.
Re: Сделать из одного массива - два
От: Mr.Delphist  
Дата: 11.11.22 12:05
Оценка: -1
Здравствуйте, snaphold, Вы писали:

S>Person

S> age
S> name

S>как из persons одним запросом через Linq получить 2 массива: ages (distinct age from persons), names (distinct name from persons) ?


А если сначала получить distinct-сочетания (age,name), а затем из них выдрать индивидуальные distinct-списки? Это не спасёт отца русской демократии?
Re[2]: Сделать из одного массива - два
От: snaphold  
Дата: 11.11.22 13:28
Оценка:
Здравствуйте, Mr.Delphist, Вы писали:

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


S>>Person

S>> age
S>> name

S>>как из persons одним запросом через Linq получить 2 массива: ages (distinct age from persons), names (distinct name from persons) ?


MD>А если сначала получить distinct-сочетания (age,name), а затем из них выдрать индивидуальные distinct-списки? Это не спасёт отца русской демократии?


у меня было ощущение что SelectMany может решить мою проблему. Я его редко юзаю и поэтому в любых непонятных случаях считаю что он умеет это)
Re: Сделать из одного массива - два
От: vaa  
Дата: 11.11.22 14:32
Оценка:
Здравствуйте, snaphold, Вы писали:

S>Есть такой массив.


S>List<Person> persons


S>Person

S> age
S> name

S>как из persons одним запросом через Linq получить 2 массива: ages (distinct age from persons), names (distinct name from persons) ?


S>то есть хотелось бы такого вида получить

S>
S>(names, ages) = persons.SelectMany(x => (n, a), n.Distinct(name), a.Distinct(a.age));
S>


UnZip

https://gist.github.com/ldub/48a4e8bf02b03b4e91b1

но раз нет в стандратной библиотеке, думаю там есть подвох

UPD посмотрите реализацию F# https://fsharp.github.io/fsharp-core-docs/reference/fsharp-collections-listmodule.html#unzip
☭ ✊ В мире нет ничего, кроме движущейся материи.
Отредактировано 12.11.2022 3:13 Разраб . Предыдущая версия .
Re[2]: Сделать из одного массива - два
От: _NN_  
Дата: 14.11.22 22:52
Оценка: 5 (1)
Здравствуйте, vaa, Вы писали:

vaa>но раз нет в стандратной библиотеке, думаю там есть подвох


Если чего-то нет не обязательно есть на это причины

Конкретно здесь объективная причина это множественный проход по перечислению.
Методы расширения LINQ построены на реализацию в один проход.

IEnumerable<IEnumerable<T>> Transpose1<T>(IEnumerable<IEnumerable<T>> list) {
    return 
        list.First().Any()
            // generate list of heads of lists   | 'concat' it with the rest of the matrix transposed
            ? (new []{list.Select(x => x.First())}).Concat(Transpose1(list.Select(x => x.Skip(1))))
            : (IEnumerable<IEnumerable<T>>) new List<List<T>>();
}
http://rsdn.nemerleweb.com
http://nemerleweb.com
Re: Сделать из одного массива - два
От: Sinclair Россия https://github.com/evilguest/
Дата: 26.11.22 09:21
Оценка: 24 (1)
Здравствуйте, snaphold, Вы писали:

S>как из persons одним запросом через Linq получить 2 массива: ages (distinct age from persons), names (distinct name from persons) ?

А зачем вам 1 запросом? Чем не устраивает 2?
(names, ages) = ((from p in persons select p.name).Distinct(), (from p in persons select p.age).Distinct());

S>то есть хотелось бы такого вида получить
S>
S>(names, ages) = persons.SelectMany(x => (n, a), n.Distinct(name), a.Distinct(a.age));
S>

В ФП все такие операции делаются через fold/reduce (Aggregate в .Net).
Тот же самый Distinct выражется через Aggregate вот таким образом:
public IEnumerable<T> Distinct<T>(this IEnumerable<T> source) => 
  source.Aggregate(new ImmutableHashSet<T>(), (set, x) => set.Add(x));

То есть начинаем с пустого множества, а затем каждый из элементов исходной коллекции складываем в это множество (игнорируя дубликаты).
С учётом этого знания, решение от IT выглядит очевидным обобщением:
(names, ages) 
  = persons.Aggregate(
    (names: new ImmutableHasSet<string>(), ages:new ImmutableHashSet<int>()), 
    (acc, person) =>(acc.names.Add(person.name), acc.ages.Add(person.age))
  );
Уйдемте отсюда, Румата! У вас слишком богатые погреба.
Отредактировано 26.11.2022 10:29 Sinclair . Предыдущая версия .
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.