Using LINQ to XML, how can I join two sets of data based on ordinal position?
Using LINQ to 开发者_运维问答XML, how can I join two sets of data based on ordinal position?
<document>
<set1>
<value>A</value>
<value>B</value>
<value>C</value>
</set1>
<set2>
<value>1</value>
<value>2</value>
<value>3</value>
</set2>
</document>
Based on the above fragment, I would like to join the two sets together such that "A" and "1" are in the same record, "B" and "2" are in the same record, and "C" and "3" are in the same record.
This is what the Enumerable.Zip extension does in .NET 4. You'd write it like so (assuming that this is the entire XDocument
):
var set1Elements = document.Element("set1").Elements();
var set2Elements = document.Element("set2").Elements();
var results = set1Elements.Zip(set2Elements,
(s1, s2) => new { Value1 = s1.Value, Value2 = s2.Value });
If you're using .NET 3.5 or earlier, it's not too difficult to write the Zip
extension:
public static IEnumerable<TResult> Zip<TFirst, TSecond, TResult>(
this IEnumerable<TFirst> first,
IEnumerable<TSecond> second,
Func<TFirst, TSecond, TResult> resultSelector)
{
using (var firstEnumerator = first.GetEnumerator())
using (var secondEnumerator = second.GetEnumerator())
{
while ((firstEnumerator.MoveNext() && secondEnumerator.MoveNext()))
{
yield return resultSelector(firstEnumerator.Current,
secondEnumerator.Current);
}
}
}
Here's another method using the overload of Select that will include an element's index
XElement set1 = document.Root.Element("set1");
XElement set2 = document.Root.Element("set2");
var query = from value1 in set1.Descendants("value").Select((ele, idx) => new { Value = ele.Value, Index = idx })
join value2 in set2.Descendants("value").Select((ele, idx) => new { Value = ele.Value, Index = idx })
on value1.Index equals value2.Index
select new { Value1 = value1.Value, Value2 = value2.Value };
精彩评论