Как сделать следующий шаг строки. C#

Сериализация чревата ловушками. Автоматическая поддержка сериализации этой формы делает часть внутренностей класса общедоступного API (который является, почему javadoc дает Вам сохраненные формы классов ).

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

Сериализация может также привести к проблемам безопасности. Способностью сериализировать любой объект это имеет ссылку на, класс может получить доступ к данным, это обычно не было бы в состоянии к (путем парсинга результирующих данных байта).

существуют другие проблемы, такие как сериализированная форма внутренних классов, не являющихся четко определенным.

Создание всех сериализуемых классов усилило бы эти проблемы. Выезд Эффективный Java Второй Выпуск , в особенности Объект 74: Реализация, сериализуемая рассудительно .

6
задан rochb 24 May 2011 в 14:45
поделиться

10 ответов

ПРИМЕЧАНИЕ: Этот ответ неверен , так как "aa" должно следовать после "Z" ... (см. Комментарии ниже)

Вот алгоритм, который может работать:

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

Таким образом, следующий шаг может быть вычислен путем анализа «числовой» -строки обратно в int, добавив 1 и затем отформатировав его обратно в базу.

Пример:

"a" == 1 -> step("a") == step(1) == 1 + 1 == 2 == "b"

Теперь ваша проблема сводится к синтаксическому анализу строки как числа с заданной базой и ее переформатированию. Быстрый поиск в Google предлагает эту страницу: http://everything2.com/title/convert+any+number+to+decimal

Как это реализовать?

  • таблица поиска букв для соответствующего номера: a = 1, b = 2, c = 3, ... Y =?, Z = 0
  • , чтобы преобразовать строку в число,
    • "ab" -> 2 * BASE ^ 0 + 1 * BASE ^ 1
    • , где BASE - это количество "цифр" (2 числа букв в алфавите, это 48?)

РЕДАКТИРОВАТЬ: Эта ссылка выглядит еще более многообещающей: http://www.citidel.org/bitstream/10117/20/12/convexp.html

11
ответ дан 8 December 2019 в 13:01
поделиться

Достаточный набор подходов, вот мой: -

Функция:

private static string IncrementString(string s)
{
  byte[] vals = System.Text.Encoding.ASCII.GetBytes(s);
  for (var i = vals.Length - 1; i >= 0; i--)
  {
    if (vals[i] < 90)
    {
      vals[i] += 1;
      break;
    }
    if (vals[i] == 90)
    {
      if (i != 0)
      {
        vals[i] = 97;
        continue;
      }
      else
      {
        return new String('a', vals.Length + 1); 
      }
    }

    if (vals[i] < 122)
    {
      vals[i] += 1;
      break;
    }

    vals[i] = 65;
    break;
  }

  return System.Text.Encoding.ASCII.GetString(vals);
}

Тесты

Console.WriteLine(IncrementString("a") == "b");
Console.WriteLine(IncrementString("z") == "A");
Console.WriteLine(IncrementString("Z") == "aa");
Console.WriteLine(IncrementString("aa") == "ab");
Console.WriteLine(IncrementString("az") == "aA");
Console.WriteLine(IncrementString("aZ") == "ba");
Console.WriteLine(IncrementString("zZ") == "Aa");
Console.WriteLine(IncrementString("Za") == "Zb");
Console.WriteLine(IncrementString("ZZ") == "aaa");
5
ответ дан 8 December 2019 в 13:01
поделиться
public static class StringStep
{
    public static string Next(string str)
    {
        string result = String.Empty;
        int index = str.Length - 1;
        bool carry;
        do
        {
            result = Increment(str[index--], out carry) + result;              
        }
        while (carry && index >= 0);
        if (index >= 0) result = str.Substring(0, index+1) + result;
        if (carry) result = "a" + result;
        return result;
    }

    private static char Increment(char value, out bool carry)
    {
        carry = false;
        if (value >= 'a' && value < 'z' || value >= 'A' && value < 'Z')
        {
            return (char)((int)value + 1);
        }
        if (value == 'z') return 'A';
        if (value == 'Z')
        {
            carry = true;
            return 'a';
        }
        throw new Exception(String.Format("Invalid character value: {0}", value));
    }
}
3
ответ дан 8 December 2019 в 13:01
поделиться

Разделите входную строку на столбцы и обработайте каждый справа налево, как если бы это была простая арифметика. Примените любой код, который у вас есть, который работает с одним столбцом, к каждому столбцу. Когда вы получаете Z, вы «увеличиваете» следующий левый столбец, используя тот же алгоритм. Если следующего левого столбца нет, вставьте букву «а».

0
ответ дан 8 December 2019 в 13:01
поделиться

Простите, что вопрос сформулирован частично. Я отредактировал вопрос так, чтобы он соответствовал требованиям, без редактирования функция закончила бы n раз за шагом, увеличивая каждое слово со строчного a до верхнего регистра z без его «повторного анализа».

Пожалуйста, перечитайте вопрос, включая отредактированную часть

0
ответ дан 8 December 2019 в 13:01
поделиться

Это частный случай системы счисления. Он имеет базу 52. Если вы напишете синтаксический анализатор и логику вывода, вы можете выполнять любую арифметику, очевидно, здесь +1 (++). Цифры от «a» до «z» и от «A» до «Z», где «a» - ноль, а «Z» - 51

. Таким образом, вам нужно написать синтаксический анализатор, который берет строку и строит int или long от него. Эта функция называется StringToInt () и реализуется прямо (преобразование символа в число (0..51), умножение на 52 и получение следующего символа)

И вам нужна обратная функция IntToString, которая также реализуется прямо (по модулю int с 52 и преобразовать результат в цифру, разделить int на 52 и повторять это до тех пор, пока int не станет нулем)

С помощью этих функций вы можете делать что-то вроде этого: IntToString (StringToInt ("ZZ") +1) // Будет "ааа"

0
ответ дан 8 December 2019 в 13:01
поделиться

Это то, что я придумал. Я не полагаюсь на преобразование ASCII int, а скорее использую массив символов. Это должно делать именно то, что вы ищете.

    public static string Step(this string s)
    {
        char[] stepChars = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ".ToCharArray();

        char[] str = s.ToCharArray();
        int idx = s.Length - 1;

        char lastChar = str[idx];


        for (int i=0; i<stepChars.Length; i++)
        {
            if (stepChars[i] == lastChar)
            {
                if (i == stepChars.Length - 1)
                {
                    str[idx] = stepChars[0];
                    if (str.Length > 1)
                    {
                        string tmp = Step(new string(str.Take(str.Length - 1).ToArray()));
                        str = (tmp + str[idx]).ToCharArray();
                    }
                    else
                        str = new char[] { stepChars[0], str[idx] };
                }
                else
                    str[idx] = stepChars[i + 1];

                break;
            }
        }

        return new string(str);
    }
0
ответ дан 8 December 2019 в 13:01
поделиться

Вам необходимо учитывать A) тот факт, что у заглавных букв десятичное значение в таблице Ascii ниже, чем у младших случай те. B) Таблица не является непрерывной AZaz - между Z и a есть символы.

public static string stepChar(string str)
{
  return stepChar(str, str.Length - 1);
}

public static string stepChar(string str, int charPos)
{
  return stepChar(Encoding.ASCII.GetBytes(str), charPos);
}

public static string stepChar(byte[] strBytes, int charPos)
{
  //Escape case 
  if (charPos < 0)
  {
    //just prepend with a and return
    return "a" + Encoding.ASCII.GetString(strBytes);
  }
  else
  {

    strBytes[charPos]++;

    if (strBytes[charPos] == 91)
    {
      //Z -> a plus increment previous char
      strBytes[charPos] = 97;
      return stepChar(strBytes, charPos - 1);                }
    else
    {
      if (strBytes[charPos] == 123)
      {
        //z -> A 
        strBytes[charPos] = 65;
      }

      return Encoding.ASCII.GetString(strBytes);
    }
  }
}

Вам, вероятно, понадобится некоторая проверка, чтобы убедиться, что входная строка содержит только символы A-Za-z


Править Приведен в порядок код и добавлена ​​новая перегрузка для удаления избыточного байта [] -> строка -> преобразование байта []

Доказательство http://geekcubed.org/random/strIncr.png

0
ответ дан 8 December 2019 в 13:01
поделиться

LetterToNum должен быть функцией, которая отображает "a" в 0 и «Z» до 51. NumToLetter обратное.

long x = "aazeiZa".Aggregate((x,y) => (x*52) + LetterToNum(y)) + 1;
string s = "";

do { // assertion: x > 0
    var c = x % 52;
    s = NumToLetter() + s;
    x = (x - c) / 52;
} while (x > 0)

// s now should contain the result
-1
ответ дан 8 December 2019 в 13:01
поделиться

Это очень похоже на то, как работали бы столбцы Excel, если бы они были неограниченными. Вы можете изменить 52 на ссылку chars.Length для упрощения модификации.

static class AlphaInt {
    private static string chars =
        "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ";

    public static string StepNext(string input) {
        return IntToAlpha(AlphaToInt(input) + 1);
    }

    public static string IntToAlpha(int num) {
        if(num-- <= 0) return "a";
        if(num % 52 == num) return chars.Substring(num, 1);
        return IntToAlpha(num / 52) + IntToAlpha(num % 52 + 1);
    }

    public static int AlphaToInt(string str) {
        int num = 0;
        for(int i = 0; i < str.Length; i++) {
            num += (chars.IndexOf(str.Substring(i, 1)) + 1)
                   * (int)Math.Pow(52, str.Length - i - 1);
        }
        return num;
    }
}
0
ответ дан 8 December 2019 в 13:01
поделиться
Другие вопросы по тегам:

Похожие вопросы: