Я думаю, что есть два ответа на этот вопрос: лучшая идиома для этой проблемы на любом языке, и лучшая идиома для этой проблемы в Java. Я также думаю, что целью этой проблемы было не объединение строк, а шаблон в целом, поэтому на самом деле не помогает показать библиотечные функции, которые могут это сделать.
Во-первых, хотя действия по окружению строки с помощью [] и созданию строки, разделенной запятыми, являются двумя отдельными действиями, в идеале это две отдельные функции.
Я думаю, что для любого языка лучше всего подходит сочетание рекурсии и сопоставления с образцом. Например, в haskell я бы сделал это:
join [] = ""
join [x] = x
join (x:xs) = concat [x, ",", join xs]
surround before after str = concat [before, str, after]
yourFunc = surround "[" "]" . join
-- example usage: yourFunc ["dog", "cat"] will output "[dog,cat]"
Преимущество написания такого кода состоит в том, что оно четко перечисляет различные ситуации, с которыми сталкивается функция, и способы ее обработки.
Еще один очень хороший способ сделать это с помощью функции типа аккумулятора. Например:
join [] = ""
join strings = foldr1 (\a b -> concat [a, ",", b]) strings
Это можно сделать и на других языках, например, c #:
public static string Join(List<string> strings)
{
if (!strings.Any()) return string.Empty;
return strings.Aggregate((acc, val) => acc + "," + val);
}
Не очень эффективен в этой ситуации, но может быть полезен в других случаях (или эффективность может не иметь значения).
К сожалению, java не может использовать ни один из этих методов. Так что в этом случае я думаю, что лучший способ - это проверять в верхней части функции случаи исключений (0 или 1 элемент), а затем использовать цикл for для обработки случая с более чем 1 элементом:
public static String join(String[] items) {
if (items.length == 0) return "";
if (items.length == 1) return items[0];
StringBuilder result = new StringBuilder();
for(int i = 0; i < items.length - 1; i++) {
result.append(items[i]);
result.append(",");
}
result.append(items[items.length - 1]);
return result.toString();
}
Эта функция четко показывает, что происходит в двух крайних случаях (0 или 1 элемент). Затем он использует цикл для всех элементов, кроме последних, и, наконец, добавляет последний элемент без запятой. Обратный способ обработки не запятого элемента на старте также легко сделать.
Обратите внимание, что строка if (items.length == 1) return items[0];
на самом деле не нужна, однако я думаю, что это делает то, что функция делает, легче определить с первого взгляда.
(Обратите внимание, что если кому-то нужно больше объяснений по поводу функций haskell / c #, спросите, и я добавлю его)