IEnumerable Прехвърляне на 2 IEnumerables в един клас

Имам 2 IEnumerables

IEnumerable<float> Distance
IEnumerable<XElement> Point

в което искам да конвертирам

IEnumerable<Subsection> subsection

където е Класът

class Subsection
{
    public float Distance
    public XElement Point
}

Но нямам представа как да направя това, опитах някои варианти на кастинг, нито един от които не проработи, защото изглежда не приемат множество списъци като входни данни.

Променливите Distance и Point се четат от xml документ, където структурата за тези две точки е подобна на:

<PLI>
    <Distance>5</Distance>
    <Point>23 22</Point>
    <Distance>7</Distance>
    <Point>21 72</Point>
    <Distance>9</Distance>
    <Point>13 32</Point>
</PLI>

Не бях сигурен как да ги прочета просто като тип подраздел, но ако някой можеше да предложи как да направя това, щеше да заобиколи нуждата ми да го конвертирам, тъй като вече няма да ги имам като IEnumerables на разстояние и точка, а като структура .

Моля, обърнете внимание, че не мога да променя XML

Благодаря

РЕДАКТИРАНЕ: XML има други елементи, както и тези, споменати в рамките на PLI тага, напр.

<PLI>
    <OtherElement1>element1value</OtherElement1>
    <OtherElement2>element2value</OtherElement2>
    <Distance>5</Distance>
    <Point>23 22</Point>
    <Distance>7</Distance>
    <Point>21 72</Point>
    <Distance>9</Distance>
    <Point>13 32</Point>
</PLI>

person Manatherin    schedule 13.12.2010    source източник
comment
Актуализирах публикацията си, за да отчета други елементи. Това засегна само не-LINQ подхода. Подходът Zip беше непроменен.   -  person Ahmad Mageed    schedule 13.12.2010


Отговори (2)


Можете да направите това с LINQ с помощта на метода Enumerable.Zip, при условие че вашият XML е балансиран (четен брой елементи за сдвояване на разстояния и точки).

var query = xml.Elements("Distance")
               .Zip(xml.Elements("Point"),
                    (d, p) => new Subsection
                    {
                        Distance = float.Parse(d.Value),
                        Point = p
                    });

Като алтернатива можете да преминете през елементите и да изградите Subsection елемента. Това може да стане по следния начин, въпреки че предполага, че вашият XML документ е балансиран и в очаквания формат.

var query = xml.Elements()
               .Where(e => e.Name.LocalName == "Distance"
                           || e.Name.LocalName == "Point");
var list = new List<Subsection>();
int count = 0;
Subsection s = null;
foreach (var element in query)
{
    if (count % 2 == 0)
        s = new Subsection { Distance = float.Parse(element.Value) };
    else
    {
        s.Point = element;
        list.Add(s);
    }

    count++;
}

Имайте предвид, че и в двата фрагмента променливата xml е XElement. За XDocument добавете свойството Root, както в xml.Root.Elements(...).

person Ahmad Mageed    schedule 13.12.2010
comment
Актуализиран е вторият подход за филтриране на Distance и Point елементи и работа само с тях. Отново, трябва да сте сигурни, че са балансирани. Ако не сте сигурни, трябва да е достатъчна предварителна .Count() проверка и на двете колекции от елементи, като се провери дали сборът им е четен (модул 2 == 0). - person Ahmad Mageed; 13.12.2010
comment
Благодаря, функцията zip беше точно това, което търсех, никога не съм я виждал преди - person Manatherin; 13.12.2010

Това не е референтно прозрачно и напълно непрепоръчително, но ако сте настроени на LINQ, това е най-добрата идея, която имам за момента за този конкретен проблем. По този начин вашата поръчка гарантирано ще бъде същата.

public class SubSection
{
    public float Distance;
    public XElement Point;

    public SubSection(XElement distance, XElement point)
    {
        Distance = float.Parse(distance.Value);
        Point = point;
    }
}
class Program
{
    static void Main(string[] args)
    {
        var c = XDocument.Parse(@"<PLI>
<Distance>5</Distance>
<Point>23 22</Point>
<Distance>7</Distance>
<Point>21 72</Point>
<Distance>9</Distance>
<Point>13 32</Point>
</PLI>");

        var sup = new List<SubSection>();
        c.Elements().Elements().Aggregate<XElement,XElement>(null, (a, d) =>
            {
                if (a == null)
                    return d;
                sup.Add(new SubSection(a, d));
                return null;
            });
        foreach (var entry in sup)
        {
            Console.WriteLine(entry.Distance);
        }

    }
}
person Squirrelsama    schedule 13.12.2010