我们可以在foreach中使用多个变量吗?
本文关键字:变量 foreach 我们 | 更新日期: 2023-09-27 17:55:46
我们可以在foreach中使用多个变量吗
foreach (var item1 in collection1;var items2 in collection2)
{
}
我想这样做,因为我需要从数据库中获取两个集合并将它们附加到 ComboBox。
使用 LINQ 联接将结果放入匿名类型的数组,然后循环访问生成的集合。
var col = collection1.Join(collection2, x => x, y => y, (x, y) => new { X = x, Y = y });
foreach (var entry in col) {
// entry.X, entry.Y
}
编辑:
在发布答案时,我假设collection1
和collection2
包含不同的类型。如果它们包含相同的类型或共享一个通用的基本类型,则有替代方法:
如果要允许重复项:
collection1.Concat(collection2); // same type
collection1.select(x => (baseType)x).Concat(collection2.select(x => (baseType)x)); // shared base type
无重复项:
collection1.Union(collection2); // same type
collection1.select(x => (baseType)x).Union(collection2.select(x => (baseType)x)); // shared base type
表单框架 4.0 及更高版本的 Zip 可以替换原始解决方案:
collection1.Zip(collection2, (x, y) => new { X = x, Y = y });
有关大多数可用 LINQ 功能的概述,请参阅 101 个 LINQ 示例。
如果没有 LINQ,请使用两个分层 foreach 循环(增加交互数)或一个 foreach 循环来创建中间类型,使用第二个循环循环访问中间集合,或者如果集合中的类型相同,则将它们添加到列表中(使用 AddRange)
,然后循环访问此新列表。
许多道路通向一个目标...由您选择一个。
您可以压缩集合
foreach (var item in collection1.Zip(collection2, (a, b) => new { A = a, B = b }))
{
var a = item.A;
var b = item.B;
// ...
}
这假设元素在同一位置匹配(例如,集合 1 中的第一个元素加入 collecion2 的第一个元素)。这是相当有效的。
不可以,您不能在循环中使用多个变量。检查语言参考。如果每个集合都有不同数量的项目,会发生什么情况?
如果要循环访问这两个集合,请尝试使用联合:
foreach (var item1 in collection1.Union(collection2))
{
...
}
foreach 用于枚举集合中的单个项。所以不,你不能。你必须一个接一个地使用它。最好使用:
void myfunc()
{}
foreach(var item1 in collection1){myfunc();}
foreach(var item2 in collection2){myfunc();}
比
foreach(var item1 in collection1)
foreach(var item2 in collection2)
{
myfunc();
}
这将运行 n*m 次。而前面的示例将仅运行 n+m 次。
从您的评论来看,我认为您真正要做的不是获取两个集合的笛卡尔乘积,而是获取两个集合的 [SQL] UNION
。您有两种选择:
-
Concat
两个集合:foreach(var items in collection1.Concat(collection2)) {}
-
只需将它们分别添加,假设您不需要通过迭代做任何花哨的事情(可能是最好/最简单的):
myComboBox.Items.AddRange(collection1); myComboBox.Items.AddRange(collection2);
但是,如果您确实想要 [SQL 伪代码] 的 n*m 笛卡尔乘积collection1 CROSS JOIN collection2
,则可以使用两个嵌套的 foreach 语句:
foreach(var item1 in collection1)
foreach(var item2 in collection2)
{
}
或者,可以在 LINQ 中联接这两者并循环访问联接的集合:
foreach(var items in (from i1 in collection1
from i2 in collection2
select Tuple.Create(i1, i2)))
{
}
您可以使用较新的语法来执行此操作:
var collection1 = new List<int>(){1,2,3,4};
var collection2 = new List<int>(){5,6,7,8};
var zip = collection1.Zip(collection2, (i,j) => (i,j));
foreach (var (item1, item2) in zip)
{
Console.WriteLine($"item1:{item1} item2:{item2}");
}
// outputs:
//item1:1 item2:5
//item1:2 item2:6
//item1:3 item2:7
//item1:4 item2:8
是否要将一个集合中的项目与另一个集合的相应项目配对?
foreach (var pair in col1.Zip(col2, (Item1, Item2) => new { Item1, Item2 })
{
//do something with pair.Item1 and pair.Item2
}
注意:如果第一个集合有 10 个项目,第二个集合有 8 个项目,您将获得 8 对;第一个集合中的最后两个项目将被丢弃,因为在第二个集合中没有可以匹配它们的东西。 更一般地说,迭代次数将Min(col1.Count(), col2.Count())
。
,然后循环访问第二个集合中的所有项?
foreach (var element in col1.Concat(col2))
{
//do something with element
}
注意:如果第一个集合有 10 个元素,第二个集合有 8 个元素,则此循环将执行 18 次,或者更一般地说,迭代次数将col1.Count() + col2.Count()
。
是否要将一个集合中的每个项目与另一个集合中的每个项目配对?
foreach (var item1 in col1)
foreach (var item2 in col2)
{
//do something with item1 and item2
}
注意:这是笛卡尔积,因此,毫不奇怪,迭代次数是集合大小的乘积。 如果我们有 10 个和 8 个项目,循环将执行 80 次。 为了保持一致性,这col1.Count() * col2.Count()
.
您可以使用迭代器:
IEnumerator <Item2Type> item2Itt = Collection2.GetEnumerator();
item2Itt.MoveNext(); // The iterator returned above is BEFORE the first element in the collection.
foreach (Item1Type item1 in collection1)
{
item1.blahblahblah;
item2Itt.Current.blahBlahBlah;
item2Itt.MoveNext();
}
我认为可以使用这种方式:
List<Type> allOfThem = new List<Type>(); //use proper type for collection
allOfThem.AddRange(collection1);
allOfThem.AddRange(collection2);
foreach (Type item in allOfThem)
{
...
}
使用枚举器是最简单的方法。可以使用两个集合中的任何一个来获取枚举器,并在另一个集合上运行枚举器。
public void MatchSentences() {
string[] OrigSentences = { "hello you", "what are you doing", "hope things are fine" };
string[] CompareSentences = { "hello you", "what are you doing", "hope things are fine" };
// Get enumerator on the second collection
var outputStrEnum = CompareSentences.GetEnumerator();
// Run foreach on the first collection
foreach (var sentence in OrigSentences) {
outputStrEnum.MoveNext();
string testAgainst = outputStrEnum.Current.ToString();
bool result = sentence.Equals(testAgainst);
Assert.IsTrue(result,
String.Format(" Expected for '{0}': {1}; Actual: '{2}'",
testAgainst, result,sentence) );
}
}