繁体   English   中英

如何迭代数组/集合/列表中的“之间”项?

[英]How do I iterate “between” items in an array / collection / list?

多年来这个问题一直困扰着我,而且当我有一个更好的解决方案时,我总觉得我想要一个黑客。 当你想要做的事,以所有列表中的项目,然后添加一些插图中的项目出现在眼前的问题。 简而言之,我想:

  • 对列表中的每个项目执行某些操作。
  • 除了列表中的最后一项之外的所有其他内容(实际上,在列表中的项目之间执行某些操作)。

例如,假设我有一个名为Equation的类:

public class Equation
{
    public string LeftSide { get; set; }
    public string Operator { get; set; }
    public string RightSide { get; set; }
}

我想迭代一个Equation列表并返回一个格式化这些项目的字符串; 类似以下内容:

public string FormatEquationList(List<Equation> listEquations)
{
    string output = string.Empty;
    foreach (Equation e in listEquations)
    {
        //format the Equation
        string equation = "(" + e.LeftSide + e.Operator + e.RightSide + ")";

        //format the "inbetween" part
        string inbetween = " and ";

        //concatenate the Equation and "inbetween" part to the output
        output += equation + inbetween;
    }
    return ouput;
}

与上面的代码的问题是,它要包括and在返回的字符串的结尾。 我知道我可以一起破解一些代码,用for循环替换foreach ,只有当它不是最后一项时才添加inbetween元素; 但这似乎是一个黑客。

有没有一种标准的方法来处理这类问题?

你基本上有一些不同的策略来处理这种问题:

  1. 处理循环外的第一个(或最后一个)项。
  2. 执行工作,然后“撤消”无关的步骤。
  3. 检测您正在处理循环内的第一个或最后一个项目。
  4. 使用更高级别的抽象,可以避免这种情况。

任何这些选项都可以是实现“项目之间”算法风格的合法方式。 您选择哪一个取决于以下内容:

  • 你喜欢哪种风格
  • “撤消工作”是多么昂贵
  • 每个“加入”步骤的成本是多少
  • 是否有任何副作用

除此之外。 对于字符串的特定情况,我个人更喜欢使用string.Join() ,因为我发现它最清楚地说明了意图。 此外,在字符串的情况下,如果您不使用string.Join() ,您应该尝试使用StringBuilder来避免创建太多临时字符串(字符串在.Net中不可变的结果)。

使用字符串连接作为示例,不同的选项分解为示例,如下所示。 (为简单起见,假设Equation有ToString()为: "(" + LeftSide + Operator + RightSide + ")"

public string FormatEquation( IEnumerable<Equation> listEquations )
{
    StringBuilder sb = new StringBuilder();

    if( listEquations.Count > 0 )
        sb.Append( listEquations[0].ToString() );
    for( int i = 1; i < listEquations.Count; i++ )
        sb.Append( " and " + listEquations[i].ToString() );
    return sb.ToString();
}

第二个选项如下:

public string FormatEquation( IEnumerable<Equation> listEquations )
{
    StringBuilder sb = new StringBuilder();
    const string separator = " and ";
    foreach( var eq in listEquations )
        sb.Append( eq.ToString() + separator );
    if( listEquations.Count > 1 )
        sb.Remove( sb.Length, separator.Length );
}

第三个看起来像:

public string FormatEquation( IEnumerable<Equation> listEquations )
{
    StringBuilder sb = new StringBuilder();
    const string separator = " and ";
    foreach( var eq in listEquations )
    {
        sb.Append( eq.ToString() );
        if( index == list.Equations.Count-1 )
            break;
        sb.Append( separator );
    }
}

最后一个选项可以在.NET中使用String.Join或Linq:

public string FormatEquation( IEnumerable<Equation> listEquations )
{
    return string.Join( " and ", listEquations.Select( eq => eq.ToString() ).ToArray() );
}

要么:

public string FormatEquation( IEnumerable<Equation> listEquations ) 
{
    return listEquations.Aggregate((a, b) => a.ToString() + " and " + b.ToString() );
}

就个人而言,我避免使用Aggregate()进行字符串连接,因为它会产生许多中间的,丢弃的字符串。 它也不是将一堆结果“加入”在一起的最明显的方式 - 它主要用于以某种随意,调用者定义的方式计算集合的“标量”结果。

您可以使用String.Join()

String.Join(" and ",listEquations.Select(e=>String.Format("({0}{1}{2})",e.LeftSide,e.Operator,e.RightSide).ToArray());

您可以使用LINQ的Aggregate运算符执行此操作:

public string FormatEquationList(List<Equation> listEquations)
{
    return listEquations.Aggregate((a, b) => 
        "(" + a.LeftSide + a.Operator + a.RightSide + ") and (" + 
              b.LeftSide + b.Operator + b.RightSide + ")");
}

如果你不想要一个foreach循环,使用带有计数器的for循环是完全合理的。 这就是为什么有多种类型的循环语句。

如果要成对处理项目,请在LINQ的Aggregate运算符处循环。

我通常在条件之前添加它,并检查它是否是第1项。

public string FormatEquationList(List<Equation> listEquations) 
{ 
    string output = string.Empty;
    foreach (Equation e in listEquations) 
    {
        //use conditional to insert your "between" data:
        output += (output == String.Empty) ? string.Empty : " and "; 

        //format the Equation 
        output += "(" + e.LeftSide + e.Operator + e.RightSide + ")"; 

    } 
    return ouput; 
}

我不得不说我会看看string.Join()函数,对于Linqiness来说就是+1。 我的例子是一个传统的解决方案。

我通常会尝试根据条件为分隔符添加前缀,而不是将它们添加到结尾。

string output = string.Empty;
for (int i = 0; i < 10; i++)
{
   output += output == string.Empty ? i.ToString() : " and " + i.ToString();
}

0和1和2和3和4和5和6和7和8和9

我喜欢已发布的String.Join方法。

但是当你不使用数组时,这通常是我解决这个问题的方法:

public string FormatEquationList(List<Equation> listEquations)
{
    string output = string.Empty;
    foreach (Equation e in listEquations)
    {
        // only append " and " when there's something to append to
        if (output != string.Empty)
            output += " and ";

        output += "(" + e.LeftSide + e.Operator + e.RightSide + ")";
    }
    return output;
}

当然,使用StringBuilder通常会更快:

public string FormatEquationList(List<Equation> listEquations)
{
    StringBuilder output = new StringBuilder();
    foreach (Equation e in listEquations)
    {
        // only append " and " when there's something to append to
        if (output.Length > 0)
            output.Append(" and ");

        output.Append("(");
        output.Append(e.LeftSide);
        output.Append(e.Operator);
        output.Append(e.RightSide);
        output.Append(")");
    }

    return output.ToString();
}

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM