我们可以在foreach中使用多个变量吗?

本文关键字:变量 foreach 我们 | 更新日期: 2023-09-27 17:55:46

我们可以在foreach中使用多个变量吗

foreach (var item1 in collection1;var items2 in collection2)
{
}

我想这样做,因为我需要从数据库中获取两个集合并将它们附加到 ComboBox。

我们可以在foreach中使用多个变量吗?

使用 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
}

编辑:

在发布答案时,我假设collection1collection2包含不同的类型。如果它们包含相同的类型或共享一个通用的基本类型,则有替代方法:

如果要允许重复项:

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。您有两种选择:

  1. Concat两个集合:

    foreach(var items in collection1.Concat(collection2)) {}
    
  2. 只需将它们分别添加,假设您不需要通过迭代做任何花哨的事情(可能是最好/最简单的):

    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) );
                }
    
            }