Foreach выполняет избыточную логику
Мои два цикла ForEach позволяют получить доступ к errorOrders
(имя пользователя и его количество ошибок) и totalOrders
(имя пользователя и его общее количество заказов).
Мой код постоянно проходит через эти два ForEaches. "Рассчитывать" на обоих errorOrders
а также totalOrders
38, и программа прекрасно просматривает все 38 пользователей. Но затем он снова и снова повторяет их, повторяя только что завершенный процесс.
Как я могу просмотреть пользователей только один раз?
foreach (KeyValuePair<string, int> error in errorOrders)
{
foreach (KeyValuePair<string, int> total in totalOrders)
{
errPercentage = ((double)error.Value / (double)total.Value);
Console.WriteLine("Percentage of errors for " + total.Key + ": " + Math.Round(errPercentage, 2) * 100 + "%");
ordersPerHour = OrdersPerHour(total.Key);
RandomOrders = RandomSelect(errPercentage, total.Key);
Console.WriteLine("Number of orders pulled : " + RandomOrders.Rows.Count);
//Print out orders randomly collected
for (int i = 0; i < RandomOrders.Rows.Count; i++)
{
Console.WriteLine(RandomOrders.Rows[i]["ControlNumber"]);
}
Console.WriteLine("\r\n");
//NumOrdersToPull = FindNumOrdersToPull(Math.Round(errPercentage,2), ordersPerHour);
}
}
5 ответов
Разделите петли, а не вкладывайте их. Помещение одного внутрь другого запускает весь дочерний цикл для каждого экземпляра родительского цикла. (Отсюда и название.)
// (shared variables here)
foreach (KeyValuePair<string, int> total in totalOrders)
{
// Code relevant to all orders here
}
foreach (KeyValuePair<string, int> error in errorOrders)
{
// Code relevant to erroneous orders only here
}
Если в циклах необходимо использовать переменные, объявите их перед первым циклом. Переменные, созданные внутри цикла, будут локальными и прекратят свое существование после завершения цикла.
Второй цикл будет проходить один раз для каждого итогового количества заказов. Если вы хотите, чтобы они проходили только один раз, не вкладывайте их. вместо этого имейте их один за другим.
foreach(total in total orders)
{
}
foreach(error in errororders)
{
}
Вам нужно будет только вложить их, если они связаны, и вам нужно было выполнить внутренний цикл один раз для каждой итерации внешнего цикла.
Попробуй это:
foreach (KeyValuePair<string, int> error in errorOrders)
{
if (totalOrder.HasKey(error.Key) {
var total = totalOrders[error.Key];
errPercentage = ((double)error.Value / (double)total);
Console.WriteLine("Percentage of errors for " + error.Key + ": " + Math.Round(errPercentage, 2) * 100 + "%");
ordersPerHour = OrdersPerHour(error.Key);
RandomOrders = RandomSelect(errPercentage, error.Key);
Console.WriteLine("Number of orders pulled : " + RandomOrders.Rows.Count);
//Print out orders randomly collected
for (int i = 0; i < RandomOrders.Rows.Count; i++)
{
Console.WriteLine(RandomOrders.Rows[i]["ControlNumber"]);
}
Console.WriteLine("\r\n");
//NumOrdersToPull = FindNumOrdersToPull(Math.Round(errPercentage,2), ordersPerHour);
}
}
Или даже только один цикл, а затем поиск другого? totalOrders - это какой-то список? если бы вы могли превратить один в словарь, вы могли бы сделать что-то вроде
foreach (KeyValuePair<string, int> total in totalOrders)
{
// do work for each order
object whatever;
if (errorOrders.TryGetValue( total.Key, out whatever ))
{
// do extra work because this order has an error
}
}
Другие ответы помогли мне прийти к такому выводу:
foreach (KeyValuePair<string, int> e in errorOrders)
{
errPercentage = GetErrPercentage(e.Key);
Console.WriteLine("Percentage of errors for " + e.Key + ": " + Math.Round(errPercentage, 2) * 100 + "%");
ordersPerHour = OrdersPerHour(e.Key);
RandomOrders = RandomSelect(errPercentage, e.Key);
}
Console.WriteLine("Number of orders pulled : " + RandomOrders.Rows.Count);
//Print out orders randomly collected
for (int i = 0; i < RandomOrders.Rows.Count; i++)
{
Console.WriteLine(RandomOrders.Rows[i]["ControlNumber"]);
}
Console.WriteLine("\r\n");
static double GetErrPercentage(string user)
{
double errPercentage = 0;
errPercentage = (double)errorOrders[user]/ (double)totalOrders[user];
return errPercentage;
}