Как я могу сделать разделение вложенных строк? - PullRequest
0 голосов
/ 05 марта 2011

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

Чтобы проиллюстрировать проблему:

string[] nested = { "mary;john;carl", "dog;cat;fish", "plainValue" }
string list = string.Join(";", nested);
string[] unnested = list.Split(';'); // EEK! returns 7 items, expected 3!

Это приведет к появлению списка "mary; john; carl; dog; cat; fish; plainValue", значение, которое я не могу разделить, чтобы получить три исходные вложенные строки.Действительно, вместо трех исходных строк я бы получил 7 строк при разбиении, и поэтому этот подход вообще не работает.

Я хочу разрешить кодирование значений в моей строке, чтобы я могмогу распаковать / разделить содержимое так, как я их упаковал / присоединился. Полагаю, мне может понадобиться убежать от строки. Сплит и строка. Присоединяйтесь, и это совершенно нормально.Я мог бы просто пропустить какой-нибудь полезный класс или метод.

  • Как разрешить упаковывать / распаковывать любые строковые значения в списки?
    Я предпочитаю аккуратные, простые решенияслишком громоздким, если это возможно.

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

Ответы [ 7 ]

2 голосов
/ 05 марта 2011

попробовать:

const char joinChar = '╗'; // make char const
string[] nested = { "mary;john;carl", "dog;cat;fish", "plainValue" };
string list = string.Join(Convert.ToString(joinChar), nested);
string[] unnested = list.Split(joinChar); // eureka returns 3!

Использование символа ascii за пределами обычного «набора» позволяет объединять и разбивать, не разрушая логику, которая разделена на символе ;.

1 голос
/ 05 марта 2011

Кодируйте ваши строки в кодировку base64 перед присоединением.

1 голос
/ 05 марта 2011

Рассматривали ли вы использование другого разделителя, например, "|"?

Таким образом, присоединяемая строка будет "mary; john; carl | dog; cat; fish | plainValue" и при вызове списка.сплит ( "|");он вернет три оригинальные строки

1 голос
/ 05 марта 2011

Ожидаемые предметы равны 7, потому что вы разделяетесь с ; символом.Я бы предложил изменить ваш код на:

string[] nested = { "mary;john;carl", "dog;cat;fish", "plainValue" }
string list = string.Join("@" nested);
string[] unnested = list.Split('@'); // 3 strings again
0 голосов
/ 05 марта 2011

Мэйби не так хороша, как ты хотел.Но здесь идет:)

    static void Main(string[] args)
    {
        string[] str = new string[] {"From;niklas;to;lasse", "another;day;at;work;", "Bobo;wants;candy"};
        string compiledString = GetAsString(str);
        string[] backAgain = BackToStringArray(compiledString);
    }

    public static string GetAsString(string[] strings)
    {
        string returnString = string.Empty;
        using (MemoryStream ms = new MemoryStream())
        {
            using (BinaryWriter writer = new BinaryWriter(ms))
            {
                writer.Write(strings.Length);
                for (int i = 0; i < strings.Length; ++i)
                {
                    writer.Write(strings[i]);
                }
            }
            ms.Flush();

            byte[] array = ms.ToArray();
            returnString = Encoding.UTF8.GetString(array);
        }
        return returnString;
    }

    public static string[] BackToStringArray(string encodedString)
    {
        string[] returnStrings = new string[0];
        byte[] toBytes = Encoding.UTF8.GetBytes(encodedString);
        using (MemoryStream stream = new MemoryStream(toBytes))
        {
            using (BinaryReader reader = new BinaryReader(stream))
            {
                int numStrings = reader.ReadInt32();
                returnStrings = new string[numStrings];
                for (int i = 0; i < numStrings; ++i)
                {
                    returnStrings[i] = reader.ReadString();
                }
            }
        }
        return returnStrings;
    }
0 голосов
/ 05 марта 2011

Я тоже придумал собственное решение.

Я мог бы закодировать длину элемента, а затем содержимое элемента. Он вообще не будет использовать string.Split и string.Join, но это решит мою проблему. Контент будет не тронут, и любой контент, который нуждается в кодировании, может, в свою очередь, использовать эту кодировку в своем пространстве содержимого.

Для иллюстрации формата (заголовок постоянной длины):

<длина содержимого> <необработанное содержимое>

Для иллюстрации формата (заголовок переменной длины):

<длина содержимого> <символ остановки заголовка> <необработанное содержимое>

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

Пример с 4 шестнадцатеричными числами (максимальная длина ffff / 65535):

0005Hello0005World

В последнем примере мы можем уменьшить это до:

5: Hello5: World

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

Вложенный пример может выглядеть так:

е: 5: Hello5: worldâ: 2: Hi4: John

  • (Список - 14 символов, включая заголовки)
    • Привет (5 символов)
    • Мир (5 символов)
  • (Список - 10 символов, включая заголовки)
    • Привет (2 символа)
    • Джон (4 символа)

Недостатком является то, что для него явно требуется длина всех элементов, даже если бы не было символа «разделяемый разделитель» (это решение не использует разделителей, если используется заголовок фиксированной длины).

0 голосов
/ 05 марта 2011

Используйте для присоединения другое значение, отличное от точки с запятой (;). Например - вы можете использовать запятую (,) и вы получите "mary;john;carl,dog;cat;fish,plainValue". Когда вы снова разделите его на основе (,) в качестве разделителя, вы должны получить исходное строковое значение.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...