【问题标题】:convert for loop to foreach with index将 for 循环转换为带索引的 foreach
【发布时间】:2016-09-26 00:09:45
【问题描述】:

我有这个ToString 用于写出对象的方法。我正在尝试将 for 循环转换为 foreach 循环。 不使用 LINQ。

任何指针将不胜感激。

 public override string ToString()
 {
     StringBuilder output = new StringBuilder();
     output.AppendFormat("{0}", count);
     for (var index = 0; index < total; index++)
     {
         output.AppendFormat("{0}{1}{2} ", array[index], array[index].GetInfo,
                              string.Join(" ", array[index].Content(index)),
                            );
     }
     return output.ToString();
 } 

【问题讨论】:

  • 为什么要近距离投票,因为这太广泛了?
  • 好的,为什么要投反对票?这世界怎么这么宽泛?
  • minimal reproducible example 在这里很有用。

标签: c# for-loop foreach tostring


【解决方案1】:

这是基于您当前代码的重构。

public override string ToString() {
    var output = new StringBuilder();
    output.AppendFormat("{0}", count);
    var index = 0;
    foreach (var item in array) {
        if (item!=null) {
            output.AppendFormat("{0}{1}{2} ", item, item.GetInfo,
                              string.Join(" ", item.Content(index++)),
                            );
        }
    }
    return output.ToString();
} 

使用 linq,您可以使用索引 Select 执行相同的操作,而无需直接调用底层使用的 foreach

public override string ToString() {
    var output = new StringBuilder();
    output.AppendFormat("{0}", count);
    array.Select((item, index) =>
        output.AppendFormat("{0}{1}{2} ", item, item.GetInfo,
                              string.Join(" ", item.Content(index)),
                            )
    );
    return output.ToString();
} 

【讨论】:

  • 感谢您的回答。如果我不想浏览array 的所有内容怎么办,因为其中一些是空的。是否有可能打破每个
  • 您可以过滤以仅获取不是null 的项目。即array.Where(item =&gt; item!=null)
  • 好的,然后在 foreach 中进行检查,您可以中断或继续
【解决方案2】:

从技术上讲,您可以这样做:

public override string ToString()
{
    StringBuilder output = new StringBuilder();
    output.Append(count);

    int index = 0;
    foreach (var item in array)
    {           
        output.Append($"{item}{item.GetInfo()}{string.Join(" ", item.Content(index))}");
        index++;
    }
    return output.ToString();
}

无论如何,你都会选择int index。根据performance 的说法,将其移至 foreach 并没有太大帮助。

如果您真的不喜欢到处编写递增索引,您也可以尝试自己的 ForEach 扩展。

public static class EnumerableExtensions
{
    public static void ForEachWithIndex<T>(this IEnumerable<T> sequence, Action<int, T> action)
    {
        // argument null checking omitted
        int i = 0;
        foreach (T item in sequence)
        {
            action(i, item);
            i++;
        }
    }
}

那么你的方法会更简单,但你还要管理一个类:

public override string ToString()
{
    StringBuilder output = new StringBuilder();
    output.Append(count);
    array.ForEachWithIndex((index, item) => output.Append($"{item}{item.GetInfo()}{string.Join("", item.Content(index))}"));
    return output.ToString();
}

为了可读性,如果你真的只是将字符串并排放置:

public override string ToString()
{
    StringBuilder output = new StringBuilder();
    output.Append(count);
    array.ForEachWithIndex((index, item) => output.Append(
        string.Concat(
            item, 
            item.GetInfo(), 
            string.Join("", item.Content(index))
            )));
    return output.ToString();
}

无论如何,string.Concat 在性能方面会更受欢迎。如果您需要格式化,请选择其他的。

【讨论】:

  • 谢谢伙计。这也有效,但我必须接受第一个进来的那个。
  • 完全没问题。谢谢。
【解决方案3】:

根据 totalcount 是什么,您可以重构为这样的:

public override string ToString()
{
    return count.ToString()
        + String.Join(" ",
            array.Select((x, n) => $"{x}{x.GetInfo}{String.Join(" ", x.Content(n))}"));
}

String.Join 的性能通常比StringBuilder 好,所以它不是一个糟糕的选择。


你去。此扩展不需要 LINQ:

public static class Ex
{
    public static IEnumerable<R> Select<T, R>(this IEnumerable<T> source, Func<T, int, R> projection)
    {
        int index = 0;
        foreach (var item in source)
        {
            yield return projection(item, index++);
        }
    }
}

【讨论】:

  • LINQ 不适合我。抱歉,最初的问题中没有说明这一点。
  • @hello - 我给了你一个非 LINQ 解决方案。
猜你喜欢
  • 2021-03-12
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-01-19
  • 1970-01-01
  • 2020-11-26
  • 1970-01-01
相关资源
最近更新 更多