Вопрос или проблема
Если у меня есть список строк, такой как {“A”, “B”, “C”, “D”}, какой код по динамической конкатенации будет самым чистым, чтобы объединить их в фразу без запятой перед последней строкой и с “и” или “или” перед последней строкой?
Например:
если у меня {“A”}, то должно быть “A”
если у меня {“A”,”B”}, то должно быть “A или B”
если у меня {“A”,”B”,”C”}, то должно быть “A, B или C”
Я бы разбил список на “последний элемент” и “все остальные”. Объединил бы “все остальные” с помощью string.Join
и добавил “последний элемент” в конце. Крайние случаи – когда в списке только один или нет элементов.
string Concatenate(List<string> strings) {
if (strings.Count < 2) {
return strings.FirstOrDefault() ?? "";
} else {
return $"{string.Join(", ", strings[..^1])} или {strings[^1]}";
}
}
Вот как я это сделал на C#, не уверен, что это самый чистый код, но проверено, что он работает для каждого из вышеуказанных сценариев:
var listOfStrings = new List<string>() { "A", "B", "C", "D" };
// замените на "и", если требуется
var concatenatorPhrase = "или";
var fullPhrase = new StringBuilder();
var firstString = listOfStrings.First();
listOfStrings.Remove(firstString);
fullPhrase.Append(firstString);
if (listOfStrings.Count > 0)
{
var lastString = listOfStrings.Last();
listOfStrings.Remove(lastString);
if (listOfStrings.Count > 0)
{
fullPhrase.Append(", ");
foreach (var str in listOfStrings)
{
fullPhrase.Append(str).Append(", ");
}
}
fullPhrase.Append($"{concatenatorPhrase} ").Append(lastString);
}
fullPhrase.ToString()
Я рассмотрел как ваш вопрос, так и ответ. И я предоставил свой код соответственно. Вы модифицируете существующий список, удаляя элементы, что можно избежать. И ваш код не выглядит чистым.
var listOfStrings = new List<string> { "A", "B", "C", "D" };
var concatenatorPhrase = "или"; // Замените на "и", если требуется
string JoinStrings(List<string> strings, string separator)
{
if (strings == null || strings.Count == 0) return string.Empty;
if (strings.Count == 1) return strings[0];
if (strings.Count == 2) return $"{strings[0]} {separator} {strings[1]}";
var allButLast = strings.Take(strings.Count - 1);
var lastString = strings.Last();
return $"{string.Join(", ", allButLast)} {separator} {lastString}";
}
var fullPhrase = JoinStrings(listOfStrings, concatenatorPhrase);
Console.WriteLine(fullPhrase);
string[][] strings =
[
["A", "B", "C", "D"],
["A", "B", "C"],
["A", "B"],
["A"]
];
foreach (var arr in strings)
{
string s = string.Join("", arr.Select((s, index) => s + arr.Count() switch
{
1 => "",
_ => (index == arr.Count() - 1) ? "" : (index == arr.Count() - 2) ? " или " : ", "
}));
Console.WriteLine(s);
}
// Вывод:
// A, B, C или D
// A, B или C
// A или B
// A
Как насчёт этого:
private static string CustomConcatenate(List<string> inputList)
{
var lengthOfList = inputList.Count;
var listWithSeparators = inputList
.Select((s, i) => ((i == 0) ? string.Empty : (i == lengthOfList - 1) ? " или " : ", ") + s);
return string.Join("", listWithSeparators);
}
// Тестовый случай XUnit просто чтобы проверить, дает ли функция ожидаемый результат или нет
[Fact]
public void ConcatTest()
{
var givenLstWithMoreThan2Elmts = new List<string> { "A", "B", "C" };
"A, B или C".Should().Be(CustomConcatenate(givenLstWithMoreThan2Elmts));
// 2-й случай
var givenLstWith2Elmts = new List<string> { "A", "B" };
"A или B".Should().Be(CustomConcatenate(givenLstWith2Elmts));
// 3-й случай
var givenLst3 = new List<string> { "A" };
"A".Should().Be(CustomConcatenate(givenLst3));
}
Ответ или решение
Конкатенация строк в виде фразы без запятой перед последней строкой и с использованием "и"/"или" перед последней строкой является распространенной задачей в программировании, в том числе в C#. Рассмотрим, как можно реализовать данное решение с помощью чистого и понятного кода.
Задача
Вам дан список строк, например, {"A", "B", "C", "D"}
. Ваша задача — динамически объединить их в одну фразу с учетом следующих правил:
- Если список пуст, возвращаем пустую строку.
- Если в списке один элемент, возвращаем его.
- Если в списке два элемента, форматируем их с помощью "или".
- Если в списке больше двух элементов, объединяем их с помощью запятой и перед последним элементом используем "или" или "и" (в зависимости от заданной логики).
Реализация
Предлагаем следующий вариант реализации функции JoinStrings
на C#:
using System;
using System.Collections.Generic;
using System.Linq;
class Program
{
static void Main()
{
var listOfStrings = new List<string> { "A", "B", "C", "D" };
string concatenatorPhrase = "or"; // Замените на "and" по необходимости
string fullPhrase = JoinStrings(listOfStrings, concatenatorPhrase);
Console.WriteLine(fullPhrase);
}
static string JoinStrings(List<string> strings, string separator)
{
if (strings == null || strings.Count == 0) return string.Empty;
if (strings.Count == 1) return strings[0];
if (strings.Count == 2) return $"{strings[0]} {separator} {strings[1]}";
var allButLast = strings.Take(strings.Count - 1);
var lastString = strings.Last();
return $"{string.Join(", ", allButLast)} {separator} {lastString}";
}
}
Объяснение кода
- Проверка на пустой список: Если список
strings
пуст, возвращаем пустую строку. - Обработка одного элемента: Если в списке один элемент, просто возвращаем его.
- Обработка двух элементов: Если элементы два, форматируем строку с использованием заданного разделителя ("и" или "или").
- Обработка более двух элементов: Для всех, кроме последнего элемента, объединяем их с запятой, а последний элемент добавляем с разделителем.
Примеры использования
- Для
{"A"}
вывод будетA
. - Для
{"A","B"}
вывод будетA or B
. - Для
{"A","B","C"}
вывод будетA, B or C
. - Для
{"A","B","C","D"}
вывод будетA, B, C or D
.
Заключение
Данный подход обеспечивает чистоту и читаемость кода, что делает его идеальным решением для задачи конкатенации строк в необходимые форматы. Вы можете легко адаптировать функцию для использования различных разделителей, просто изменив переменную concatenatorPhrase
.
Такой метод также легко тестировать с помощью юнит-тестов, что делает ваш код надежным и поддерживаемым.