簡體   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