Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/304.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/linq/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 使用linq比较不同类型的列表_C#_Linq - Fatal编程技术网

C# 使用linq比较不同类型的列表

C# 使用linq比较不同类型的列表,c#,linq,C#,Linq,我有一个列表,列出了从XML加载的内容 XML如下所示: <TablesToSynchronize> <Table name="dbo.Table1" /> <Table name="dbo.Table2" /> <Table name="dbo.Table3" /> <Table name="dbo.Table4" /> </TablesToSynchronize> VarTest2工作正常,但它只返回表1中的XElem

我有一个列表,列出了从XML加载的内容

XML如下所示:

<TablesToSynchronize>
<Table name="dbo.Table1" />
<Table name="dbo.Table2" />
<Table name="dbo.Table3" />
<Table name="dbo.Table4" />
</TablesToSynchronize>
VarTest2工作正常,但它只返回表1中的XElement。我想循环args并检查其中是否有任何项与XElement attribute name.Value匹配

我错过了什么

args包含dbo.Table1、dbo.Table2、dbo.Table3

更新:test2给了我一个包含dbo.Table1的XElement列表。test给我一个空的字符串列表


输出应该是一个列表

有两种方法可以实现您想要的结果,一种是使用Where,另一种是使用JOIN

您可以应用联接以获得以下结果:

  var mytest = TableSettings.Descendants("Table").Join(arggs, x => x.Attribute("name").Value, y => y, (x, y) => new { Element = x });
您可以将Where作为


如果您的数据很小,那么它不应该给您决定使用的数据带来很多性能改进。但是如果你有大量的数据,阅读评论和更多关于这方面的东西,你应该自己决定你想采用哪种方法

以下内容将返回两个元素:

args = new[] { "dbo.Table1", "dbo.Table3" };
var test = (from elt in TableSettings.Descendants("Table")
            where args.Contains(elt.Attribute("name").Value)
            select elt).ToList();
Debug.Assert(test.Count==2);

或等效方法链:

var test = TableSettings.Descendants("Table")
                        .Where(elt => args.Contains(elt.Attribute("name").Value))
                        .ToList();
XAttribute可显式转换为基本.NET类型之一,因此必须使用字符串转换。否则.NET会将XAttribute实例与字符串值进行比较

如果您有很多参数,并且担心Contains很慢,则可以将字符串数组转换为字典:

var argsDict = args.ToDictionary(x => x);
var test = TableSettings.Descendants("Table").                    
                Where(elt => argsDict.ContainsKey(elt.Attribute("name").Value))
                .ToList();
10000000次迭代的快速测试会返回这些不太有意义的结果:

地点:33466320 加入:32560386 字典:22998512 哈希集:25979814个刻度 Where和Join之间的差异可以忽略~2%,很容易归因于噪声。不过,字典或哈希集的速度要快得多~30%

事实上,等效方法之间的差异波动很大,基本上没有意义

这并不奇怪,因为字典/哈希集本质上就像SQL中的索引一样。事实上,当联接中的两个表之一相对较小时,SQLServer将使用哈希联接

如果需要从参数中访问多个键,则字典的性能可能会更好,因为您可以在单个操作中查找和检索匹配值。这类似于在SQL中使用覆盖索引:

MyOtherClass v=null;
var test = from elt in TableSettings.Descendants("Table")
           let value = elt.Attribute("name").Value
           where argsDict.TryGetValue(value, out v)
           select new {elt, v};
这在C5中是相当难看的。这就是C 6中现在已经废弃的声明表达式的作用:

var test = from elt in TableSettings.Descendants("Table")
           let value = elt.Attribute("name").Value
           where argsDict.TryGetValue(value, out var v)
           select new {elt, v};

对不起,应该是dbo.Table。Will Update您可以在TableSettings中使用类似于from x的内容。在args中使用DegenantStable from y join x.Attributename.Value equals y select xmaybe这将起作用test=test.wheret=>args.ToList.Containst.ToList预期的输出是什么?是元素列表还是字符串列表?测试变量的内容有什么问题?请在你的问题中包括这些细节。@Grundy这就是解决方案。我错过了一个简单的案例感官特征。。。。thanks@PanagiotisKanavos为什么你认为加入太多了?@PanagiotisKanavos现在当你提到我在这里读到它时,它提到加入在大数据的情况下实际上表现得更好。因为where生成笛卡尔积和联接只接受匹配的值。在这种情况下,筛选器和联接是相同的,因为筛选器依赖于第二个集合,所以我认为它更经典的是内部联接,而不是filter@PanagiotisKanavos,join in linq是一些集合的简单交集,具体的实现取决于所使用的providerI我不明白为什么使用Join太过分了。如果您想使用Linq,在这里使用它是正确的方法。其中x=>foo.Containsx更难阅读,速度较慢,并且根据您的使用情况,可能需要额外的选择。在这种情况下,最好使用HashSet而不是simplearray@Grundy或者一本字典。性能上的差异是没有意义的。虽然Join掩盖了语句试图实现的内容,但HashSet和Dictionary*之间的区别仅限于键本身taste@Grundy如果您需要参数中的多个键,则最好使用字典,这类似于在SQL中使用覆盖索引。避免额外查找在这种情况下,您只使用字典中的键,因此:-
var argsDict = args.ToDictionary(x => x);
var test = TableSettings.Descendants("Table").                    
                Where(elt => argsDict.ContainsKey(elt.Attribute("name").Value))
                .ToList();
MyOtherClass v=null;
var test = from elt in TableSettings.Descendants("Table")
           let value = elt.Attribute("name").Value
           where argsDict.TryGetValue(value, out v)
           select new {elt, v};
var test = from elt in TableSettings.Descendants("Table")
           let value = elt.Attribute("name").Value
           where argsDict.TryGetValue(value, out var v)
           select new {elt, v};