LINQ to list
От: coddy  
Дата: 16.03.10 18:41
Оценка:
Добрый вечер!
Подскажите с таким вопросом:
есть список объектов Point3D. (Где Point3D — структураc 3ми полями-координатами int X, int Y, int Z и полем int Turn (может содержаться 3 значения — 0, 1 и 2))

Возможно ли средствами LINQ решить такую задачу:
Получить элементы списка, со значением "2" и у рядом с которыми есть пустые элементы (т.е. со значением "0")
Re: LINQ to list
От: _FRED_ Черногория
Дата: 16.03.10 18:58
Оценка:
Здравствуйте, coddy, Вы писали:

C>Подскажите с таким вопросом:

C>есть список объектов Point3D. (Где Point3D — структураc 3ми полями-координатами int X, int Y, int Z и полем int Turn (может содержаться 3 значения — 0, 1 и 2))

C>Возможно ли средствами LINQ решить такую задачу:

C>Получить элементы списка, со значением "2"

В каком из полей?

C>и у рядом с которыми есть пустые элементы (т.е. со значением "0")


Что значит "рядом"?

Линк, я так понимаю, нужен к коллекциям, то есть System.Linq.Enumerable?
Help will always be given at Hogwarts to those who ask for it.
Re: LINQ to list
От: Lloyd Россия  
Дата: 16.03.10 19:16
Оценка: 3 (1) +1
Здравствуйте, coddy, Вы писали:

C>Возможно ли средствами LINQ решить такую задачу:

C>Получить элементы списка, со значением "2" и у рядом с которыми есть пустые элементы (т.е. со значением "0")

Оно?


using System;
using System.Collections.Generic;
using System.Linq;

namespace ConsoleApplication2 {
    public static class ZipHelper {
        public static IEnumerable<W> Zip3<T, U, V, W>(IEnumerable<T> seq1, IEnumerable<U> seq2, IEnumerable<V> seq3, Func<T, U, V, W> resultSelector) {
            using (var enum1 = seq1.GetEnumerator())
            using (var enum2 = seq2.GetEnumerator())
            using (var enum3 = seq3.GetEnumerator()) {
                while (enum1.MoveNext() && enum2.MoveNext() && enum3.MoveNext()) {
                    yield return resultSelector(enum1.Current, enum2.Current, enum3.Current);
                }
            }
        }
    }
    class Program {
        static void Main() {
            var points = new[] {
                new { X = 1, Y = 2, Z = 3, Turn = 0}, 
                new { X = 2, Y = 3, Z = 4, Turn = 0}, 
                new { X = 3, Y = 4, Z = 5, Turn = 2}, 
                new { X = 4, Y = 5, Z = 6, Turn = 0}, 
                new { X = 5, Y = 6, Z = 7, Turn = 0}, 
                new { X = 6, Y = 7, Z = 8, Turn = 2}, 
                new { X = 7, Y = 8, Z = 9, Turn = 0}, 
                new { X = 8, Y = 9, Z = 0, Turn = 0}, 
                new { X = 9, Y = 0, Z = 1, Turn = 2}, 
            };

            var q =
                from triple in ZipHelper.Zip3(points, points.Skip(1), points.Skip(2), (l, m, r) => new { l, m, r })
                where triple.m.Turn == 2 && triple.l.Turn == 0 && triple.r.Turn == 0
                select triple.m;

            foreach (var p in q) {
                Console.WriteLine(p);
            }
        }
    }
}
Re[2]: LINQ to list
От: coddy  
Дата: 16.03.10 21:32
Оценка:
Здравствуйте, Lloyd, Вы писали:

L>Оно?


Оно, спасибо.
Re: LINQ to list
От: Oyster Украина https://github.com/devoyster
Дата: 17.03.10 08:57
Оценка: 3 (1)
Здравствуйте, coddy, Вы писали:

C>Возможно ли средствами LINQ решить такую задачу:

C>Получить элементы списка, со значением "2" и у рядом с которыми есть пустые элементы (т.е. со значением "0")

Уже предложили перенести функцию zip из функциональных языков, можно портировать еще и window, которая создаёт плавающее окно заданного размера:

public static IEnumerable<IEnumerable<T>> Window<T>(this IEnumerable<T> self, int windowSize)
{
    int index = 0;
    var window = new List<T>(windowSize);
    window.AddRange(new T[windowSize]);
    foreach (var item in self)
    {
        bool initializing = index < windowSize;

        if (!initializing)
        {
            window = window.Skip(1).ToList();
            window.Add(default(T));
        }

        int itemIndex = initializing ? index : windowSize - 1;
        window[itemIndex] = item;

        index++;
        bool initialized = index >= windowSize;
        if (initialized)
            yield return new List<T>(window);
    }
}

Тогда задача решается примерно таким кодом:

var q =
    from triple in points.Window(3)
    let arr = triple.ToArray()
    where arr[1].Turn == 2 && arr[0].Turn == 0 && arr[2].Turn == 0
    select arr[1];

Функцию Window() я написал не сам, а нашёл в библиотеке Cadenza, где и аналог Zip3() тоже есть.
... << RSDN@Home 1.2.0 alpha 4 rev. 1419>>
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.