Создайте массив строк из более крупной строки после разделения

У меня есть строковый ввод, который выглядит как var input = "AB-PQ-EF=CD-IJ=XY-JK". Я хочу знать, есть ли способ использовать метод string.split() в C# и LINQ, чтобы я мог получить массив строк, который выглядит как этот var output = ["AB-PQ", "PQ-EF", "EF=CD", "CD-IJ", "IJ=XY", "XY-JK"]. В настоящее время я делаю то же преобразование вручную, повторяя входную строку.

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

Ipsit Gaur 13.07.2018 13:25

Я знаю, что разделителей будет только два '-', '='

pango89 13.07.2018 13:28

Но они также присутствуют там, где вам не нужно разбивать строку

Ipsit Gaur 13.07.2018 13:28

Да, именно поэтому я подумал, есть ли способ объединить возможности LINQ с split () для достижения этой цели.

pango89 13.07.2018 13:31

Твоя струна всегда такая? Значение 2 символа, разделителя, 2 символа и т. д.

Haytam 13.07.2018 13:35

Вы рассматривали возможность использования регулярных выражений?

mnieto 13.07.2018 13:35

@Haytam Нет, разделители фиксированы, но количество окружающих их символов не фиксировано. Это может быть 3 символа, 4 символа и т. д.

pango89 13.07.2018 13:37
Стоит ли изучать PHP в 2026-2027 годах?
Стоит ли изучать PHP в 2026-2027 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
5
7
156
7
Перейти к ответу Данный вопрос помечен как решенный

Ответы 7

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

string input = "ABC-PQ-EF=CD-IJ=XYZ-JK";
string s = Regex.Replace(input, @"((?<=[=-])[A-Z]+(?=[=-]))", "$1~$1");
Console.WriteLine(s);
var items = Regex.Split(s, @"(?<=[A-Z]{2}[=-][A-Z]{2})[~]");
foreach (var item in items)
{
    Console.WriteLine(item);
}

ABC-PQ~PQ-EF~EF=CD~CD-IJ~IJ=XYZ~XYZ-JK
ABC-PQ
PQ-EF
EF=CD
CD-IJ
IJ=XYZ
XYZ-JK

Демо

Если вы внимательно посмотрите на самую первую строку вывода выше, вы увидите трюк, который я использовал. Я просто соединил нужные пары через другой разделитель (в идеале ~ больше нигде в вашей строке не появляется). Затем нам просто нужно разделить по этому разделителю.

Как сказал OP, количество символов не установлено на 2.

Haytam 13.07.2018 13:38

@Haytam Я обобщил свой ответ, чтобы охватить переменное количество символов.

Tim Biegeleisen 13.07.2018 13:40

Не не-имеющий-постоянный-фиксированный-разделитель останавливает работу одиночного вызова Regex.Split, он должен дублировать буквы.

Rawling 13.07.2018 13:41

@Rawling Я не понимаю ваш комментарий или то, что вы пытаетесь здесь сказать. Если в моем ответе есть изъян, укажите на него.

Tim Biegeleisen 13.07.2018 13:42

Протестируйте его со строкой ABC-PQ-EFZ=CD-IJ=XYZ-JK, последний вывод неверен XYZ-J JK

Haytam 13.07.2018 13:42

@TimBiegeleisen В вашем примере я ожидаю, что последняя строка в массиве будет «J-JK».

pango89 13.07.2018 13:45

@ pango89 Я исправил. Это непростая задача.

Tim Biegeleisen 13.07.2018 13:47

@ Тим, где вы говорите Если бы у вас был постоянный фиксированный разделитель, вы бы смотрели только на один вызов Regex.split, я считаю, что вы ошибаетесь. Даже если бы у вас был только один разделитель, вы все равно не смогли бы Split, так что каждая буква на входе появлялась в двух элементах на выходе. И наоборот, если бы Split действительно работал, он, вероятно, работал бы независимо от количества возможных разделителей.

Rawling 13.07.2018 13:51

@Rawling Я думаю, что теперь понимаю, о чем вы говорите. Но если вы читаете мой ответ, я переделываю строку так, чтобы каждая группа является была аккуратно разделена одним фиксированным разделителем. Это было сутью моего (возможно, не оптимального) ответа.

Tim Biegeleisen 13.07.2018 13:55
Ответ принят как подходящий

Можете ли вы использовать регулярное выражение вместо разделения?

var input = "AB-PQ-EF=CD-IJ=XY-JK";
var pattern = new Regex(@"(?<![A-Z])(?=([A-Z]+[=-][A-Z]+))");
var output = pattern.Matches(input).Cast<Match>().Select(m => m.Groups[1].Value).ToArray();

Как использовать регулярное выражение, если я также хочу выполнить преобразование output => input?

pango89 12.09.2018 12:53

Для решения, использующего string.Split и LINQ, нам просто нужно отслеживать длину каждой части по мере продвижения, чтобы разделитель можно было извлечь из исходной строки, например:

var input = "ABC-PQ-EF=CDED-IJ=XY-JKLM";

var split = input.Split('-', '=');

int offset = 0;

var result = split
            .Take(split.Length - 1)
            .Select((part, index) => {
                offset += part.Length;
                return $"{part}{input[index + offset]}{split[index + 1]}";})
            .ToArray();

Вы можете попробовать следующий подход: Здесь мы разделим строку на основе специальных символов. Затем мы переберем элементы в цикле и будем выбирать до следующей группы символов. Пример: получить AB и получить значения до PQ

        string valentry = "AB-PQ-EF=CD-IJ=XY-JK";
        List<string> filt = Regex.Split(valent, @"[\-|\=]").ToList();

        var listEle = new List<string>();
        fil.ForEach(x => 
            {
                if (valentry .IndexOf(x) != valentry .Length - 2)
                {
                    string ele = valentry.Substring(valentry .IndexOf(x), 5);
                    if (!String.IsNullOrEmpty(ele))
                        listEle.Add(ele);
                }
            });

Не могли бы вы приспособить что-то подобное? Просто нужно изменить факторизацию.

        List<string> lsOut = new List<string>() { };

        string sInput = "AB-PQ-EF=CD-IJ=XY-JK";
        string sTemp = "";


        for (int i = 0; i < sInput.Length; i++)
        {

            if ( (i + 1) % 6 == 0)
            {
                continue;
            }

            // add to temp
            sTemp += sInput[i];

            // multiple of 5, add all the temp to list
            if ( (i + 1 - lsOut.Count) % 5 == 0)
            {
                lsOut.Add(sTemp);
                sTemp = "";
            }

            if (sInput.Length == i + 1)
            {
                lsOut.Add(sTemp);
            }

        }
        string input = "AB-PQ-EF=CD-IJ=XY-JK";
        var result = new Regex(@"(?<![A-Z])(?=([A-Z]+[=-][A-Z]+))").Matches(input)
            .Cast<Match>().Select(m => m.Groups[1].Value).ToArray();
        foreach (var item in result)
        {
            Console.WriteLine(item);
        }

Недавно изучал Haskell, поэтому вот рекурсивное решение.

static IEnumerable<string> SplitByPair(string input, char[] delimiter)
{
    var sep1 = input.IndexOfAny(delimiter);
    if (sep1 == -1)
    {
        yield break;
    }
    var sep2 = input.IndexOfAny(delimiter, sep1 + 1);
    if (sep2 == -1)
    {
        yield return input;
    }
    else
    {
        yield return input.Substring(0, sep2);
        foreach (var other in SplitByPair(input.Substring(sep1 + 1), delimiter))
        {
            yield return other;
        }
    }
}

Хорошие вещи

  • Это лениво
  • Легко распространить на другие условия и другие типы данных. Однако в C# это немного сложно, потому что C# не хватает Haskell List.span и сопоставления с образцом.

Другие вопросы по теме