C# 如何在两个ienumerables之间使用任意
我的asp.net MVC web应用程序中包含以下代码:C# 如何在两个ienumerables之间使用任意,c#,linq,entity-framework,asp.net-mvc-4,C#,Linq,Entity Framework,Asp.net Mvc 4,我的asp.net MVC web应用程序中包含以下代码: var currentport = tms.TMSSwitchPorts .Where(a => a.SwitchID == fromID) .Select(a2 => a2.PortNumber) .ToList(); if (currentport.Any(tms.TMSS
var currentport = tms.TMSSwitchPorts
.Where(a => a.SwitchID == fromID)
.Select(a2 => a2.PortNumber)
.ToList();
if (currentport.Any(tms.TMSSwitchPorts
.Where(a => a.SwitchID == toID)
.Select(a => a.PortNumber)
.ToList()
)
)
{
// do something
}
但是我无法以这种方式使用.Any()
,尽管我在两个列表中都选择了PortNumber字段
有人能提供建议吗?如果您的目标是jwg在其评论中描述的,您可以:
var currentportFrom = tms.TMSSwitchPorts
.Where(a => a.SwitchID == fromID)
.Select(a2 => a2.PortNumber)
.ToList();
var currentportTo = tms.TMSSwitchPorts
.Where(a => a.SwitchID == fromID)
.Select(a2 => a2.PortNumber)
.ToList();
if(currentportFrom.Any(cp => currentportTo.Contains(cp))
{
//do something
}
如果您的目标如jwg在其评论中所述,您可以:
var currentportFrom = tms.TMSSwitchPorts
.Where(a => a.SwitchID == fromID)
.Select(a2 => a2.PortNumber)
.ToList();
var currentportTo = tms.TMSSwitchPorts
.Where(a => a.SwitchID == fromID)
.Select(a2 => a2.PortNumber)
.ToList();
if(currentportFrom.Any(cp => currentportTo.Contains(cp))
{
//do something
}
取
SwitchID==toID
的类似列表
var alreadyUsed = tms.TMSSwitchPorts
.Where(a => a.SwitchID == toID)
.Select(a2 => a2.PortNumber)
.ToList();
然后检查两个列表中是否都没有显示任何内容
if (currentPort.Intersect(alreadyUsed).Any())
{ // do something }
说明:
Any()。如上所述,它自己检查容器中的任何元素。如@BenAaronson的答案(比这个答案略好)所示,它检查IEnumerable
是否包含函数参数返回true的任何元素
list1.Any(HasSomeProperty)
其中,HasSomeProperty
是一个函数,它接受list1
的元素并返回bool;或更常见于lambda:
list1.Any(x => SomePropertyHoldsFor(x))
编辑:
我说@BenAaronson的答案更好,因为它允许一些我认为我的解决方案没有的“短路”优化。这些都在对他的答复的评论中提到。然而,通过一些尝试和错误,我发现Intersect确实会自动进行相同的优化——特别是它缓存一个IEnumerable的“输出”,以便与另一个IEnumerable的每个元素进行比较,而不是每次都遍历它。因此,我的解决方案更好,因为Intersect
会自动完成您需要考虑的Ben方法;)@sloth的答案涉及到一种不同的自动优化,而且对于使用询问者心目中的Queryable
进行数据库查询来说,这要好得多
-它不是真正的“缓存”,但它只访问每个IEnumerable
一次。取SwitchID==toID
的类似列表
var alreadyUsed = tms.TMSSwitchPorts
.Where(a => a.SwitchID == toID)
.Select(a2 => a2.PortNumber)
.ToList();
然后检查两个列表中是否都没有显示任何内容
if (currentPort.Intersect(alreadyUsed).Any())
{ // do something }
说明:
Any()。如上所述,它自己检查容器中的任何元素。如@BenAaronson的答案(比这个答案略好)所示,它检查IEnumerable
是否包含函数参数返回true的任何元素
list1.Any(HasSomeProperty)
其中,HasSomeProperty
是一个函数,它接受list1
的元素并返回bool;或更常见于lambda:
list1.Any(x => SomePropertyHoldsFor(x))
编辑:
我说@BenAaronson的答案更好,因为它允许一些我认为我的解决方案没有的“短路”优化。这些都在对他的答复的评论中提到。然而,通过一些尝试和错误,我发现Intersect确实会自动进行相同的优化——特别是它缓存一个IEnumerable的“输出”,以便与另一个IEnumerable的每个元素进行比较,而不是每次都遍历它。因此,我的解决方案更好,因为Intersect
会自动完成您需要考虑的Ben方法;)@sloth的答案涉及到一种不同的自动优化,而且对于使用询问者心目中的Queryable
进行数据库查询来说,这要好得多
-它不是真正的“缓存”,但它只访问每个IEnumerable
一次。根据jwg的评论,您可以使用包含的匹配项检查第一组端口(从)和第二组端口(到)之间是否匹配:
var fromPorts = tms.TMSSwitchPorts
.Where(a => a.SwitchID == fromID)
.Select(a2 => a2.PortNumber);
if (tms.TMSSwitchPorts
.Any(a => a.SwitchID == toID &&
fromPorts.Contains(a.PortNumber)))
根据jwg的评论,您可以使用包含匹配项检查第一组端口(从)和第二组端口(到)之间是否匹配:
var fromPorts = tms.TMSSwitchPorts
.Where(a => a.SwitchID == fromID)
.Select(a2 => a2.PortNumber);
if (tms.TMSSwitchPorts
.Any(a => a.SwitchID == toID &&
fromPorts.Contains(a.PortNumber)))
您可以使用一个简单的Join
,在数据库中高效、完整地执行此操作:
var match = tms.TMSSwitchPorts.Where(a => a.SwitchID == fromID)
.Join(tms.TMSSwitchPorts.Where(a => a.SwitchID == toID),
(a) => a.PortNumber,
(b) => b.PortNumber,
(a, b) => true).Any();
if (match) { ... }
生成的SQL应该如下所示
SELECT
(CASE
WHEN EXISTS(
SELECT NULL AS [EMPTY]
FROM [TMSSwitchPorts] AS [t0]
INNER JOIN [TMSSwitchPorts] AS [t1] ON [t0].[PortNumber] = [t1].[PortNumber]
WHERE ([t0].[SwitchID] = @p0) AND ([t1].[SwitchID] = @p1)
) THEN 1
ELSE 0
END) AS [value]
因此,除了单个1
或0
在网络上移动之外,您没有任何数据,也不必将应用程序内存弄得乱七八糟
代码
if (currentport.Any(tms.TMSSwitchPorts
.Where(a => a.SwitchID == toID)
.Select(a => a.PortNumber)
.ToList()
)
将不起作用,因为Any
需要一个Func
形式的谓词,但您可以向它传递一个列表(假设PortNumber
是一个int
)。您可以使用简单的连接在数据库中高效且完全地执行此操作:
var match = tms.TMSSwitchPorts.Where(a => a.SwitchID == fromID)
.Join(tms.TMSSwitchPorts.Where(a => a.SwitchID == toID),
(a) => a.PortNumber,
(b) => b.PortNumber,
(a, b) => true).Any();
if (match) { ... }
生成的SQL应该如下所示
SELECT
(CASE
WHEN EXISTS(
SELECT NULL AS [EMPTY]
FROM [TMSSwitchPorts] AS [t0]
INNER JOIN [TMSSwitchPorts] AS [t1] ON [t0].[PortNumber] = [t1].[PortNumber]
WHERE ([t0].[SwitchID] = @p0) AND ([t1].[SwitchID] = @p1)
) THEN 1
ELSE 0
END) AS [value]
因此,除了单个1
或0
在网络上移动之外,您没有任何数据,也不必将应用程序内存弄得乱七八糟
代码
if (currentport.Any(tms.TMSSwitchPorts
.Where(a => a.SwitchID == toID)
.Select(a => a.PortNumber)
.ToList()
)
将不起作用,因为Any
需要一个Func
形式的谓词,但您向它传递一个列表(假设PortNumber
是int
).你想做什么?@ThomasLevesque我想确保当前端口号中没有一个已经分配给switchID==toID思考一下:如果switchID
是fromID
,那么它就不能是toID
,除非fromID==toID
。。。所以你只需要测试它。@ThomasLevesque,不,他正在测试是否有任何元素具有SwitchID==fromID
和PortNumber==X
,其中其他元素具有SwitchID=toID
和PortNumber==X
(对于任何X)。@jwg,也许。。。很难从当前代码猜出您想做什么?@ThomasLevesque我想确保当前端口号中没有一个已经分配给switchID==toID思考一下:如果switchID
是fromID
,那么它就不能是toID
,除非fromID==toID
。。。所以你只需要测试它。@ThomasLevesque,不,他正在测试是否有任何元素具有SwitchID==fromID
和PortNumber==X
,其中其他元素具有SwitchID=toID
和PortNumber==X
(对于任何X)。@jwg,也许。。。很难从当前的代码中猜到,但通过这种方式,我将从数据库中检索所有记录,我试图做的是发布