Eric Lippert's challenge “comma-quibbling”, best answer?

后端 未结 27 2244
日久生厌
日久生厌 2020-12-01 06:59

I wanted to bring this challenge to the attention of the stackoverflow community. The original problem and answers are here. BTW, if you did not follow it before, you should

27条回答
  •  青春惊慌失措
    2020-12-01 07:23

    Another variant - separating punctuation and iteration logic for the sake of code clarity. And still thinking about perfomrance.

    Works as requested with pure IEnumerable/string/ and strings in the list cannot be null.

    public static string Concat(IEnumerable strings)
    {
        return "{" + strings.reduce("", (acc, prev, cur, next) => 
                   acc.Append(punctuation(prev, cur, next)).Append(cur)) + "}";
    }
    private static string punctuation(string prev, string cur, string next)
    {
        if (null == prev || null == cur)
            return "";
        if (null == next)
            return " and ";
        return ", ";
    }
    
    private static string reduce(this IEnumerable strings, 
        string acc, Func func)
    {
        if (null == strings) return "";
    
        var accumulatorBuilder = new StringBuilder(acc);
        string cur = null;
        string prev = null;
        foreach (var next in strings)
        {
            func(accumulatorBuilder, prev, cur, next);
            prev = cur;
            cur = next;
        }
        func(accumulatorBuilder, prev, cur, null);
    
        return accumulatorBuilder.ToString();
    }
    

    F# surely looks much better:

    let rec reduce list =
        match list with
        | []          -> ""
        | head::curr::[]  -> head + " and " + curr
        | head::curr::tail  -> head + ", " + curr :: tail |> reduce
        | head::[] -> head
    
    let concat list = "{" + (list |> reduce )  + "}"
    

提交回复
热议问题