Algorithm for joining e.g. an array of strings

后端 未结 16 1771
陌清茗
陌清茗 2021-01-01 21:40

I have wondered for some time, what a nice, clean solution for joining an array of strings might look like. Example: I have [\"Alpha\", \"Beta\", \"Gamma\"] and want to join

相关标签:
16条回答
  • 2021-01-01 22:16

    Most languages nowadays - e.g. perl (mention by Jon Ericson), php, javascript - have a join() function or method, and this is by far the most elegant solution. Less code is better code.

    In response to Mendelt Siebenga, if you do require a hand-rolled solution, I'd go with the ternary operator for something like:

    separator = ","
    foreach (item in stringCollection)
    {
        concatenatedString += concatenatedString ? separator + item : item
    }
    
    0 讨论(0)
  • 2021-01-01 22:16

    The following is no longer language-agnostic (but that doesn't matter for the discussion because the implementation is easily portable to other languages). I tried to implement Luke's (theretically best) solution in an imperative programming language. Take your pick; mine's C#. Not very elegant at all. However, (without any testing whatsoever) I could imagine that its performance is quite decent because the recursion is in fact tail recursive.

    My challenge: give a better recursive implementation (in an imperative language). You say what “better” means: less code, faster, I'm open for suggestions.

    private static StringBuilder RecJoin(IEnumerator<string> xs, string sep, StringBuilder result) {
        result.Append(xs.Current);
        if (xs.MoveNext()) {
            result.Append(sep);
            return RecJoin(xs, sep, result);
        } else
            return result;
    }
    
    public static string Join(this IEnumerable<string> xs, string separator) {
        var i = xs.GetEnumerator();
        if (!i.MoveNext())
            return string.Empty;
        else
            return RecJoin(i, separator, new StringBuilder()).ToString();
    }
    
    0 讨论(0)
  • 2021-01-01 22:17

    For pure elegance, a typical recursive functional-language solution is quite nice. This isn't in an actual language syntax but you get the idea (it's also hardcoded to use comma separator):

    join([]) = ""

    join([x]) = "x"

    join([x, rest]) = "x," + join(rest)

    In reality you would write this in a more generic way, to reuse the same algorithm but abstract away the data type (doesn't have to be strings) and the operation (doesn't have to be concatenation with a comma in the middle). Then it usually gets called 'reduce', and many functional languages have this built in, e.g. multiplying all numbers in a list, in Lisp:

    (reduce #'* '(1 2 3 4 5)) => 120

    0 讨论(0)
  • 2021-01-01 22:18

    I usually go with something like...

    list = ["Alpha", "Beta", "Gamma"];
    output = "";
    separator = "";
    for (int i = 0; i < list.length ; i++) {
      output = output + separator;
      output = output + list[i];
      separator = ", ";
    }
    

    This works because on the first pass, separator is empty (so you don't get a comma at the start, but on every subsequent pass, you add a comma before adding the next element.

    You could certainly unroll this a little to make it a bit faster (assigning to the separator over and over isn't ideal), though I suspect that's something the compiler could do for you automatically.

    In the end though, I suspect pretty this is what most language level join functions come down to. Nothing more than syntax sugar, but it sure is sweet.

    0 讨论(0)
提交回复
热议问题