C#/Unity/Linq - 如何检查列表列表是否包含特定的另一个列表?
C# / Unity / Linq - How to check if a list of lists contains a specific another list?
我有一个这样的整数列表:
public List<List<int>> Paths = new List<List<int>>
{
new List<int>{0,1 },
new List<int>{1,2 },
new List<int>{1,3 },
new List<int>{2,3 },
new List<int>{2,4 },
new List<int>{3,4 },
new List<int>{4,5 },
};
我有一条路径,它只是一个整数列表:
List<int> path = new List<int>{4,5};
如何检查 Paths
是否包含 path
?
我试过 if(Paths.Contains(path))
并且它总是产生 false
,即使我知道我在那里有一个 {4, 5}
的列表。
我正在做一个统一的项目,我读到一些可以使用 linq 完成的魔法,所以我在标题主题中标记了它以供将来的 google 用户使用。 ;)
非常感谢您的帮助!
编辑:
我想出了这个临时解决方案,但我觉得它可以做得更优雅:
public bool CheckIfPathsHaveConnection(List<int> connection)
{
bool hasElement = false;
foreach(List<int> path in Paths)
{
if(path[0] == connection[0] && path[1] == connection[1])
{
hasElement = true;
break;
}
else
{
hasElement = false;
}
}
return hasElement;
}
编辑2:
谢谢大家的回复,我真的很感激你的努力。每个答案都很有帮助并且值得作为解决方案,不幸的是我只能选择一个作为解决方案,所以我选择了解释最多的一个。
尝试if (Paths.Any(x => x[0] == path[0] && x[1] == path[1]))
如果你想要一个 linq 解决方案,你可以使用 Any()
and All()
:
的组合
var containsPath = Paths.Any(p => p // any sub-list in 'Paths'
.All(q => // all elements of sub-list
path.Contains(q))); // are contained in 'path'
如果你想知道现有路径的索引,试试这个
var index = IfExist(paths,path);
var exist = index >= 0;
public int IfExist(List<List<int>> paths, List<int> path)
{
for (int i = 0; i < paths.Count; i++)
if (paths[i][0] == path[0] && (paths[i][1] == path[1])) return i;
return -1;
}
if(Paths.Contains(path))
在你的情况下 returns 总是 false
因为 List<T>
是一个 class => 引用类型并且你检查了引用相等性(它需要完全相同列表的实例),但你创建了一个 new
。
对于实际列表和更多一般情况,您可以使用
using System.Linq;
...
// If you use array or list doesn't matter for Linq / IEnumerable
var index = paths.FindIndex(p => p.SequenceEqual(new []{1, 2});
if(index >= 0)
{
...
}
returns 是第一个遇到的具有相同顺序的相同项目的列表的索引,或者 -1
如果找到 none。
见
但是,如果总是只有两个项目,那么我根本不会使用列表,而是使用 IEquatable
and especially GetHashCode
进行适当的实现(用于任何基于散列的集合,如 Dictionary
、HashSet
等)例如
public class Path : IEquatable<Path>
{
public int Start;
public int End;
public Path(int start, int end)
{
Start = start;
End = end;
}
public override int GetHashCode()
{
return Start.GetHashCode() ^ End.GetHashCode();
}
public bool Equals(Path path)
{
return path.Start == Start && path.End == End;
}
public override bool Equals(object obj)
{
if (obj == null || ! (obj is Path path))
return false;
else
return Equals(path);
}
public static bool operator == (Path a, Path b)
{
if (((object)a) == null || ((object)b) == null)
return object.Equals(a, b);
return a.Equals(b);
}
public static bool operator != (Path a, Path b)
{
if (((object)a) == null || ((object)b) == null)
return ! object.Equals(a, b);
return ! (a.Equals(b));
}
}
然后你可以简单地拥有一个
public List<Path> Paths = new List<Path>
{
new Path (0,1),
new Path (1,2),
new Path (1,3),
....
}
并在完全不使用 Linq 的情况下获取索引
// Since you now properly implemented Equals this now compares
// the values rather than the reference
var index = paths.IndexOf(new Path(1, 2));
if(index >= 0)
{
...
}
您想要的是测试 Paths
中的任何路径是否等于 path
:
var ans = Paths.Any(p => p.SequenceEqual(path));
我有一个这样的整数列表:
public List<List<int>> Paths = new List<List<int>>
{
new List<int>{0,1 },
new List<int>{1,2 },
new List<int>{1,3 },
new List<int>{2,3 },
new List<int>{2,4 },
new List<int>{3,4 },
new List<int>{4,5 },
};
我有一条路径,它只是一个整数列表:
List<int> path = new List<int>{4,5};
如何检查 Paths
是否包含 path
?
我试过 if(Paths.Contains(path))
并且它总是产生 false
,即使我知道我在那里有一个 {4, 5}
的列表。
我正在做一个统一的项目,我读到一些可以使用 linq 完成的魔法,所以我在标题主题中标记了它以供将来的 google 用户使用。 ;)
非常感谢您的帮助!
编辑: 我想出了这个临时解决方案,但我觉得它可以做得更优雅:
public bool CheckIfPathsHaveConnection(List<int> connection)
{
bool hasElement = false;
foreach(List<int> path in Paths)
{
if(path[0] == connection[0] && path[1] == connection[1])
{
hasElement = true;
break;
}
else
{
hasElement = false;
}
}
return hasElement;
}
编辑2: 谢谢大家的回复,我真的很感激你的努力。每个答案都很有帮助并且值得作为解决方案,不幸的是我只能选择一个作为解决方案,所以我选择了解释最多的一个。
尝试if (Paths.Any(x => x[0] == path[0] && x[1] == path[1]))
如果你想要一个 linq 解决方案,你可以使用 Any()
and All()
:
var containsPath = Paths.Any(p => p // any sub-list in 'Paths'
.All(q => // all elements of sub-list
path.Contains(q))); // are contained in 'path'
如果你想知道现有路径的索引,试试这个
var index = IfExist(paths,path);
var exist = index >= 0;
public int IfExist(List<List<int>> paths, List<int> path)
{
for (int i = 0; i < paths.Count; i++)
if (paths[i][0] == path[0] && (paths[i][1] == path[1])) return i;
return -1;
}
if(Paths.Contains(path))
在你的情况下 returns 总是 false
因为 List<T>
是一个 class => 引用类型并且你检查了引用相等性(它需要完全相同列表的实例),但你创建了一个 new
。
对于实际列表和更多一般情况,您可以使用
using System.Linq;
...
// If you use array or list doesn't matter for Linq / IEnumerable
var index = paths.FindIndex(p => p.SequenceEqual(new []{1, 2});
if(index >= 0)
{
...
}
returns 是第一个遇到的具有相同顺序的相同项目的列表的索引,或者 -1
如果找到 none。
见
但是,如果总是只有两个项目,那么我根本不会使用列表,而是使用 IEquatable
and especially GetHashCode
进行适当的实现(用于任何基于散列的集合,如 Dictionary
、HashSet
等)例如
public class Path : IEquatable<Path>
{
public int Start;
public int End;
public Path(int start, int end)
{
Start = start;
End = end;
}
public override int GetHashCode()
{
return Start.GetHashCode() ^ End.GetHashCode();
}
public bool Equals(Path path)
{
return path.Start == Start && path.End == End;
}
public override bool Equals(object obj)
{
if (obj == null || ! (obj is Path path))
return false;
else
return Equals(path);
}
public static bool operator == (Path a, Path b)
{
if (((object)a) == null || ((object)b) == null)
return object.Equals(a, b);
return a.Equals(b);
}
public static bool operator != (Path a, Path b)
{
if (((object)a) == null || ((object)b) == null)
return ! object.Equals(a, b);
return ! (a.Equals(b));
}
}
然后你可以简单地拥有一个
public List<Path> Paths = new List<Path>
{
new Path (0,1),
new Path (1,2),
new Path (1,3),
....
}
并在完全不使用 Linq 的情况下获取索引
// Since you now properly implemented Equals this now compares
// the values rather than the reference
var index = paths.IndexOf(new Path(1, 2));
if(index >= 0)
{
...
}
您想要的是测试 Paths
中的任何路径是否等于 path
:
var ans = Paths.Any(p => p.SequenceEqual(path));