作者: | 来源:互联网 | 2023-09-17 12:36
c#
我有 2 个不同的正则表达式匹配项,目前使用 2 个 foreach 循环来获取匹配值。但是,就目前而言,如果一个 foreach 有效,则另一个无效。
尝试 1
foreach (string dir in multiTrimmed1)
{
foreach (string dir2 in multiTrimmed2)
{
var forVal2= dir.Replace("$", "").Replace(" ", "");
var forVal3 = dir2.Replace(",", "");
var parsedParams= new ParsedMethod()
{
Value1= forVal1,
Value2 = Convert.ToDecimal(forVal2),
Value3 = Convert.ToDecimal(forVal3),
Value4 = forVal4
};
MergeAllValues(parsedParams);
}
}
所以这里的问题是 multiTrimmed1 和 multiTrimmed2 每个都有 string[4] 。
假设 A、B、C 和 D。在我的尝试 1 中,我希望 forVal2 和 forVal3 正确地通过循环。
我的意思是,当 forVal2 是 A 时,forVal3 也是 A - 将其发送到 MergeAllValues,接下来,B 和 B - 将其发送到 MergeAllValues,接下来,C 和 C - 将其发送到 MergeAllValues,然后 D 和 D - 发送到 MergeAllValues。
目前只有一个循环有效。如果 forVal3 的值更改为 A、B、C 和 D——那么 forVal2 就在 A 处停止。
尝试 2
bool loopAgain = true;
while (loopAgain)
{
loopAgain = false;
foreach (string dir in multiTrimmed1)
{
foreach (string dir2 in multiTrimmed2)
{
var forVal2= dir.Replace("$", "").Replace(" ", "");
var forVal3 = dir2.Replace(",", "");
var parsedParams= new ParsedMethod()
{
Value1= forVal1,
Value2 = Convert.ToDecimal(forVal2),
Value3 = Convert.ToDecimal(forVal3),
Value4 = forVal4
};
MergeAllValues(parsedParams);
loopAgain = true;
break;
}
}
在这种情况下,forVal2 得到的值很好,但 forVal3 保持在 A
尝试 3
bool loopAgain = true;
while (loopAgain)
{
loopAgain = false;
foreach (string dir in multiTrimmed1)
{
var forVal2= dir.Replace("$", "").Replace(" ", ""); foreach (string dir2 in multiTrimmed2)
{
var forVal3 = dir2.Replace(",", "");
var parsedParams= new ParsedMethod()
{
Value1= forVal1,
Value2 = Convert.ToDecimal(forVal2),
Value3 = Convert.ToDecimal(forVal3),
Value4 = forVal4
};
MergeAllValues(parsedParams);
loopAgain = true;
break;
}
}
仍然只有工作循环有效。我怎样才能使两者都工作?
回答
您已经断言multiTrimmed1
并multiTrimmed2
基于元素位置具有 1:1 的关系,因此我们可以使用.Zip
:
foreach (var (dir, dir2) in multiTrimmed1.Zip(multiTrimmed2, (a,b) => (a, b)))
{
string forVal2 = dir.Replace("$", "").Replace(" ", "");
string forVal3 = dir2.Replace(",", "");
var parsedParams = new ParsedMethod()
{
Value1 = forVal1,
Value2 = Convert.ToDecimal(forVal2),
Value3 = Convert.ToDecimal(forVal3),
Value4 = forVal4
};
MergeAllValues(parsedParams);
}
网上试试
本质上,我们在这里所做的是同时循环遍历multiTrimmed1
并在每个位置(from和from )multiTrimmed2
生成一个ValueTuple
元素。然后我们将其分解,以便我们可以单独访问这些值。a
multiTrimmed1
b
multiTrimmed2
var (dir, dir2)
您上面的代码出现问题的原因是,对于具体的集合,例如List
或 数组 ( T[]
),foreach
每次都会从头开始。
所以当你写这样的东西时:
foreach (var a in colA)
{
foreach (var b in colB)
{
}
}
您说的是“对于 colA 中的每个项目,运行以下代码”(它本身恰好也包含一个循环。因此您不会同时循环两个集合,而是循环遍历外部集合 ( colA
) 和每个项目在 colA 中,您还将浏览 colB 中的每个项目。
Zip 的方法是从 中取出一个项目colA
并从 中取出一个项目colB
,执行您的合并功能,然后产生该值。然后它从下一个项目中取出colA
下一个项目colB
并产生它们。这允许您同时有效地循环遍历两个集合。
因此,为了阐明它在内部的作用,您可以Zip
使用以下近似值实现您自己的方法:
public static IEnumerable MyZip(IEnumerable eA, IEnumerable eB, Func mergeFunc)
{
var aEnumerator = eA.GetEnumerator(); // get an enumerator for eA
var bEnumerator = eB.GetEnumerator(); // get an enumerator for eB
// while there are more items to be read in a AND b
while (aEnumerator.MoveNext() && bEnumerator.MoveNext())
{
// execute the mergeFunction on the value from a and the value from b and store the result
T itemResult = mergeFunc(aEnumerator.Current, bEnumerator.Current);
// return the result to the caller
yield return itemResult;
}
}
网上试试