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

时间:2013-01-25 06:29:53

标签: c# asp.net-mvc-4

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

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

}

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

9 个答案:

答案 0 :(得分:13)

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

如果没有LINQ,则使用两个分层的foreach循环(增加交互次数)或一个foreach循环来创建一个中间类型,第二个循环来迭代中间体集合,或者如果集合中的类型相同,则将它们添加到一个列表(使用AddRange)然后迭代这个新列表。

许多道路都会导致一个目标...由你来选择一个。

答案 1 :(得分:4)

您可以压缩收藏品

foreach (var item in collection1.Zip(collection2, (a, b) => new {  A = a, B = b }))
{
  var a = item.A;
  var b = item.B;
  // ...
}

这假设元素在相同位置匹配(例如,collection1中的第一个元素连接collecion2的第一个元素)。这非常有效。

答案 2 :(得分:3)

不,你不能在foreach中循环使用多个变量。检查language reference。如果每个集合都有不同数量的项目,会发生什么?

如果要迭代两个集合,请尝试使用union:

foreach (var item1 in collection1.Union(collection2))
{
   ...
}

答案 3 :(得分:1)

根据你的评论判断,我认为你真正要做的是获得两个集合的笛卡尔积,而是两个集合的[SQL] UNION。您有两种选择:

  1. Concat两个集合:

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

    myComboBox.Items.AddRange(collection1);
    myComboBox.Items.AddRange(collection2);
    

  3. 但是,如果您确实需要[SQL伪代码] collection1 CROSS JOIN collection2的n * m笛卡尔积,则可以使用两个嵌套的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)))
    {
    }
    

答案 4 :(得分:1)

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次。

答案 5 :(得分:0)

您想将一个集合中的项目与另一个集合中的相应项目配对吗?

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()

答案 6 :(得分:0)

您可以使用迭代器:

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

答案 7 :(得分:0)

使用枚举器是最简单的方法。您可以使用这两个集合中的任何一个来获取枚举数,并在另一个集合上运行foreach。


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

答案 8 :(得分:-1)

我认为可以使用这种方式:

List<Type> allOfThem = new List<Type>(); //use proper type for collection
allOfThem.AddRange(collection1);
allOfThem.AddRange(collection2);

foreach (Type item in allOfThem)
{
...
}