0

我有一个复杂的案例:我有三个 XML 文件,我需要同时读取它们并根据匹配获取结果。下面是一个有效的(但假的)示例,与我正在做的几乎相似。

例如,我有两个 xml 文件,两者相似,但在标签和属性方面,但内容(语言)不同。我正在同时阅读两种语言,就像在 C# 文件中的代码中一样:

XElement x1 = XElement.Load (@"abc.xml");
XElement x2 = XElement.Load (@"xyz.xml");


var ch = from var1 in x1.Elements("language1") 
         where var1.Attribute("index").Value == "1"
         from var2 in x2.Elements("language2")
         where var2.Attribute("index").Value == var1.Attribute("index").Value
         select dictChapter as new
         {  
             sentenceNumber = var1.Attribute("index").Value,
             SentenceInLanguage1 = var1.Attribute("text").Value,
             SentenceInLanguage2 = var2.Attribute("text").Value,
         };

ListBox.DataContext = ch;

这里的问题是,x1 包含 1000 个句子,所以 x2。上面的逻辑就像一个嵌套循环一样工作,这大大减慢了处理速度。它像

x1.1 -> x2.1:1000
x1.2 -> x2.1:1000

或者

for i in x1
  for j in x2

有没有更好更有效的方法从 x1 和 x2 中选择句子,其中 x1 的句子 id 等于 x2 的句子 id?

4

3 回答 3

1

据我了解你想要的,

你可以用它join来做到这一点。

这是一个很好的示例链接LINQ to XML:加入 Xml 数据(Wriju 的博客)

...或类似的东西...

var root = (from var1 in x1.Elements("language1")
            join var2 in x2.Elements("language2") on (string)var1.Attribute("index") equals (string)var2.Attribute("index")
            select new
            {
                SentenceNumber = (string)var1.Attribute("index"),
                SentenceInLanguage1 = (string)var1.Element("text"),
                SentenceInLanguage2 = (string)var2.Element("text")
            });
于 2012-04-17T15:01:30.553 回答
1

在 Linq 中,以下语句是等效的,并且将提供相同的结果:

from i1 in items1
from i2 in items2
where i1 == i2

from i1 in items1
join i2 in items2 on i1 equals i2

它们甚至会被翻译成相同的 SQL(使用 Linq to SQL)。join对于这两种情况下的 MS SQL,结果 SQL 将包含 join 子句(这就是为什么在查询数据库时不需要使用不太灵活的原因。

然而,对于Linq to ObjectsLinq to XML,两者都将以不同的方式执行。第一个将导致嵌套循环,第二个不会。

因此,您只需要更改您的实现以join按照@NSGaga 的建议使用。

另一个优化是添加.ToList()

ListBox.DataContext = ch;

我不确定数据绑定,但由于 linq 的延迟性质,您的表达式可能会被多次重新评估。

于 2012-04-17T15:20:59.280 回答
0

简单的!只需按顺序浏览每个文件。在第一遍:创建一个字典sentenceNumber > SentenceInlanguage1

SentenceInLanguage1在您的第二遍中,按照您显示的代码创建您的可枚举,并粘贴来自变量的第一遍的数据。

如果您更愿意同时遍历这两个,只需获取一个枚举器 ( GetEnumerator) 并在一个普通的旧循环中遍历它们,然后在循环体的末尾为两个枚举器while移动到下一个。XElement

于 2012-04-17T14:50:32.420 回答