Re[6]: Детский вопрос по LINQ
От: Юнусов Булат Россия  
Дата: 09.10.08 21:24
Оценка:
Здравствуйте, Константин Л., Вы писали:

КЛ>я бы написал правило для fxcop, которое бы на IEnumerable.Count выдавало warning. Можно даже в компайлер добавить


Тогда надо чтобы компилятор определял что имеет дело не с ICollection<> иначе будет ругаться почем зря.
Re[7]: Детский вопрос по LINQ
От: Константин Л.  
Дата: 09.10.08 22:02
Оценка:
Здравствуйте, Юнусов Булат, Вы писали:

ЮБ>Здравствуйте, Константин Л., Вы писали:


КЛ>>я бы написал правило для fxcop, которое бы на IEnumerable.Count выдавало warning. Можно даже в компайлер добавить


ЮБ>Тогда надо чтобы компилятор определял что имеет дело не с ICollection<> иначе будет ругаться почем зря.


если у объекта статический тип IEnumerable<>, я бы заставил ругаться всегда
Re: Детский вопрос по LINQ
От: Юнусов Булат Россия  
Дата: 09.10.08 22:13
Оценка: 16 (2)
Здравствуйте, SergASh, Вы писали:

Еще один вариант и спать
    var digits = new[] { 1, 2, 3 }.AsEnumerable();
    var german = new[]  { "ein", "zwei", "drei" }.AsEnumerable();
    var enumerator = german.GetEnumerator();
    var t = digits.SelectMany(d => { enumerator.MoveNext(); return new[] { enumerator.Current }; }, (digit, phrase) => new { Digit = digit, Phrase = phrase });
Re[8]: Детский вопрос по LINQ
От: Юнусов Булат Россия  
Дата: 09.10.08 22:14
Оценка:
Здравствуйте, Константин Л., Вы писали:

КЛ>если у объекта статический тип IEnumerable<>, я бы заставил ругаться всегда


Злые вы, кто нить поставит ворнинги как егоги и будет мучатся — оно тебе надо?
Re[9]: Детский вопрос по LINQ
От: Константин Л.  
Дата: 09.10.08 22:39
Оценка: +1
Здравствуйте, Юнусов Булат, Вы писали:

ЮБ>Здравствуйте, Константин Л., Вы писали:


КЛ>>если у объекта статический тип IEnumerable<>, я бы заставил ругаться всегда


ЮБ>Злые вы, кто нить поставит ворнинги как егоги и будет мучатся — оно тебе надо?


просто count, enumerable & perfomance вещи несовместимые. однако так легко их совместить, не заметив
Re[2]: Детский вопрос по LINQ
От: samius Япония http://sams-tricks.blogspot.com
Дата: 09.10.08 22:39
Оценка: 8 (1)
Здравствуйте, Юнусов Булат, Вы писали:

ЮБ>Здравствуйте, SergASh, Вы писали:


ЮБ>Еще один вариант и спать

ЮБ>
ЮБ>    var digits = new[] { 1, 2, 3 }.AsEnumerable();
ЮБ>    var german = new[]  { "ein", "zwei", "drei" }.AsEnumerable();
ЮБ>    var enumerator = german.GetEnumerator();
ЮБ>    var t = digits.SelectMany(d => { enumerator.MoveNext(); return new[] { enumerator.Current }; }, (digit, phrase) => new { Digit = digit, Phrase = phrase });
ЮБ>

Отличная идея! Чуть подправлю:
var enumerator = german.GetEnumerator();

var q = digits.SelectMany(
    d => enumerator.MoveNext() ? new[] { enumerator.Current } : new string[] {},
    (digit, phrase) => new { Digit = digit, Phrase = phrase });


Единственная проблема — запрос не вызвать повторно и перечислитель не освободится.
Re[3]: Детский вопрос по LINQ
От: Юнусов Булат Россия  
Дата: 09.10.08 23:13
Оценка:
Здравствуйте, samius, Вы писали:

S>Единственная проблема — запрос не вызвать повторно и перечислитель не освободится.


Что есть то есть
Re: Детский вопрос по LINQ
От: Lloyd Россия  
Дата: 10.10.08 08:39
Оценка: 3 (1)
Здравствуйте, SergASh, Вы писали:

SAS>Интересует человеческий вариант на LINQ-операторах, а не это убожество, приведенное ниже.


Убожество №2:
using System;
using System.Linq;

class Program {
    static void Main() {
        var digits = new[] { 1, 2, 3 };
        var german = new[] { "ein", "zwei", "drei" };
        var q = Enumerable
            .Repeat(new { de = digits.GetEnumerator(), ge = german.GetEnumerator() }, int.MaxValue)
            .Select(_ => _.de.MoveNext() && _.ge.MoveNext() ? new { d = _.de.Current, g = _.ge.Current, e = _ } : null)
            .TakeWhile(_ => _ != null)
            .Select((_, i) => {
                if (i == 0) {
                    if (_.e.de is IDisposable)
                        ((IDisposable)_.e.de).Dispose();
                    if (_.e.ge is IDisposable)
                        ((IDisposable)_.e.ge).Dispose();
                }
                return new { _.d, _.g };
            });
        foreach (var i in q)
            Console.WriteLine(i);
    }
}

... << RSDN@Home 1.2.0 alpha 4 rev. 1111>>
Re[3]: Детский вопрос по LINQ
От: adanov  
Дата: 11.10.08 09:29
Оценка: 5 (1)
Здравствуйте, samius, Вы писали:

S>Отличная идея! Чуть подправлю:

S>var enumerator = german.GetEnumerator();
S>var q = digits.SelectMany(
S>    d => enumerator.MoveNext() ? new[] { enumerator.Current } : new string[] {},
S>    (digit, phrase) => new { Digit = digit, Phrase = phrase });
S>


И еще чуть подправим, чтобы решение было как тост, коротким и лаконичным

var e = german.GetEnumerator();

var c = from d in digits
    select new { Digit = d, Phrase = e.MoveNext() ? e.Current : null };


S>Единственная проблема — запрос не вызвать повторно и перечислитель не освободится.

Да, это проблема.
Re[2]: Детский вопрос по LINQ
От: adanov  
Дата: 11.10.08 11:09
Оценка:
Здравствуйте, Lloyd, Вы писали:

L>Убожество №2:


Вопрос на засыпку: Почему не работает с List<> ?

var digits = new List<int> { 1, 2, 3 };
var german = new List<string> { "ein", "zwei", "drei" };
//...

Сомнения взяли, насчет Dispose() енумераторов на первой итерации.
Как после первой итерации будет выполняться Select к енумераторам, когда они уже будут Dispose'd ???
Массивы возвращают енумератор, который не поддерживает IDisposable, поэтому пример не актуальный.
Re[4]: Детский вопрос по LINQ
От: adanov  
Дата: 11.10.08 14:04
Оценка:
A>var e = german.GetEnumerator();

A>var c = from d in digits
A>    select new { Digit = d, Phrase = e.MoveNext() ? e.Current : null }; 
A>

S>>Единственная проблема — запрос не вызвать повторно и перечислитель не освободится.
A>Да, это проблема.

А так можно от проблемы избавиться, завернув получение енумератора в тело запроса:
var c = from z in Enumerable.Range(1, 1)  // это, конечно, загогулина  :(  
        let b = german.GetEnumerator()
        from Digit in digit
        select new { Digit, Phrase = b.MoveNext() ? b.Current : null };
Re: Детский вопрос по LINQ
От: adanov  
Дата: 11.10.08 16:25
Оценка:
Здравствуйте, SergASh, Вы писали:

SAS>Есть две последовательности одинаковой длины. Как для них построить соединение, которое бы соотносило элементы с одинаковыми индексами?

SAS>То есть на входе { 1, 2, 3 }, { "ein", "zwei", "drei" }. А на выходе { { 1, "ein" }, { 2, "zwei" }, { 3, "drei" } }.
SAS>Интересует человеческий вариант на LINQ-операторах...

Вот такой вариант получился (спасибо за идею использования .GetEnumerator'a Юнусову Булату):
int[] digit = { 1, 2, 3 };
string[] german = { "qwe", "ads", "zxc" };

var c = from _ in Enumerable.Range(1, 1)  // эта кривизна нужна для встраивания в запрос следующего оператора
        let e = german.GetEnumerator()
        from Digit in digit
        select new { Digit, Phrase = e.MoveNext() ? e.Current : null };

foreach (var x in c)Console.WriteLine(x);

// можно использовать многократно
foreach (var x in c) Console.WriteLine(x);

1. Только LINQ операторы. Понятно. Масштабируемо для разного количества входных списков.
Только одно выражение (функция ?).
2. Пример устойчив к разной длине списков,
выравнивая длину резульитрующего списка по первому списку
и заполняя хвост второго списка null'ами
3. Можно использовать многогратно без необходимости инициализации енумератора,
т.к. его инициализация завернута внутри запроса.
Re[10]: Детский вопрос по LINQ
От: AndrewVK Россия http://blogs.rsdn.org/avk
Дата: 11.10.08 20:14
Оценка:
Здравствуйте, Константин Л., Вы писали:

КЛ>просто count, enumerable & perfomance вещи несовместимые.


Совсем не обязательно. Вот пример (надеюсь, понятно, что речь не о производительности самого метода интегрирования).
... << RSDN@Home 1.2.0 alpha 4 rev. 1111 on Windows Vista 6.0.6001.65536>>
AVK Blog
Re[3]: Детский вопрос по LINQ
От: Lloyd Россия  
Дата: 12.10.08 10:33
Оценка:
Здравствуйте, adanov, Вы писали:

A>Сомнения взяли, насчет Dispose() енумераторов на первой итерации.

A>Как после первой итерации будет выполняться Select к енумераторам, когда они уже будут Dispose'd ???
A>Массивы возвращают енумератор, который не поддерживает IDisposable, поэтому пример не актуальный.

Ну тогда можно Dispose-ы в TakeWhile-ы засунуть.
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.