Сконкатенировать список строк в фразу без запятой перед последней строкой и с “и”/”или” перед последней строкой.

Вопрос или проблема

Если у меня есть список строк, такой как {“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"}. Ваша задача — динамически объединить их в одну фразу с учетом следующих правил:

  1. Если список пуст, возвращаем пустую строку.
  2. Если в списке один элемент, возвращаем его.
  3. Если в списке два элемента, форматируем их с помощью "или".
  4. Если в списке больше двух элементов, объединяем их с помощью запятой и перед последним элементом используем "или" или "и" (в зависимости от заданной логики).

Реализация

Предлагаем следующий вариант реализации функции 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}";
    }
}

Объяснение кода

  1. Проверка на пустой список: Если список strings пуст, возвращаем пустую строку.
  2. Обработка одного элемента: Если в списке один элемент, просто возвращаем его.
  3. Обработка двух элементов: Если элементы два, форматируем строку с использованием заданного разделителя ("и" или "или").
  4. Обработка более двух элементов: Для всех, кроме последнего элемента, объединяем их с запятой, а последний элемент добавляем с разделителем.

Примеры использования

  • Для {"A"} вывод будет A.
  • Для {"A","B"} вывод будет A or B.
  • Для {"A","B","C"} вывод будет A, B or C.
  • Для {"A","B","C","D"} вывод будет A, B, C or D.

Заключение

Данный подход обеспечивает чистоту и читаемость кода, что делает его идеальным решением для задачи конкатенации строк в необходимые форматы. Вы можете легко адаптировать функцию для использования различных разделителей, просто изменив переменную concatenatorPhrase.

Такой метод также легко тестировать с помощью юнит-тестов, что делает ваш код надежным и поддерживаемым.

Оцените материал
Добавить комментарий

Капча загружается...