Как получить непрерывные символы в C #? - PullRequest
6 голосов
/ 02 ноября 2010

У меня есть

List<String> MyList=new List<string>();

Мне нужно заполнить список MyList значениями n.

если значение n равно 2, список MyList будет содержать

"A","B"

если 10, то

"A","B","C"....."J"

если 30, то

"A"....."Z","AA","AB",AC","AD"

если 1000, то

"A",....."Z","AA","AB"......"AZ","BA","BB"......."BZ"........"YZ","AAA",AAB".....
and so on

Я не знаю, как это сделать.

Пожалуйста, помогите мне сделать это любым способом, используя LINQ или LAMBDA Expression

Ответы [ 6 ]

6 голосов
/ 02 ноября 2010

Редактировать 2 :

Вероятно, это самый простой способ реализовать это . Я проверил, все отлично работает. Вы можете генерировать бесконечное количество строк.

public IEnumerable<string> GenerateStrings()
{
    foreach(string character in Alphabet())
    {
      yield return character;
    }

    foreach (string prefix in GenerateStrings())
    {
      foreach(string suffix in Alphabet())
      {
        yield return prefix + suffix;
      }
    }
}

public IEnumerable<string> Alphabet()
{
    for(int i = 0; i < 26; i++)
    {
      yield return ((char)('A' + i)).ToString();
    }
}

Материал, который я написал раньше:

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

Это довольно коротко и просто:

string GetString(int index)
{
  if (index < 26)
  {
    return ((char)('A' + index)).ToString();
  }
  return GetString(index / 26 - 1) + GetString(index % 26);
}

использование (также может быть введено в другой метод:

List<string> strings = Enumerable.Range(0, 1000)
  .Select(x => GetString(x))
  .ToList();

Это рабочий код, только что написал тест для него.


Редактировать: например, приложение "полный путь linq" GetString:

public void IEnumerale<string> GenerateStrings()
{
  int index = 0;
  // generate "infinit" number of values ...
  while (true)
  {
     // ignoring index == int.MaxValue
     yield return GetString(index++);
  }
}

List<string> strings = GenerateStrings().Take(1000).ToList();
3 голосов
/ 02 ноября 2010

Я сделал нечто подобное в SQL некоторое время назад.

В переводе на C # это функция для создания кода из числа:

public static string GetCode(int id) {
  string code, chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
  if (id <= chars.Length) {
    code = chars.Substring(id - 1, 1);
  } else {
    id--;
    int value = chars.Length, adder = 0;
    while (id >= value * (chars.Length + 1) + adder) {
      adder += value;
      value *= chars.Length;
    }
    code = chars.Substring((id - adder) / value - 1, 1);
    id = ((id - adder) % value);
    while (value > 1) {
      value /= chars.Length;
      code += chars.Substring(id / value, 1);
      id = id % value;
    }
  }
  return code;
}

Тогдавы просто получаете числа от 1 и выше и переводите в коды:

var codes = Enumerable.Range(1, 1000).Select(n => GetCode(n));

Предел функции в настоящее время равен "ZZZZZZ" или 321272406. (После этого вы получаете деление на ноль.)

Обратите внимание, что эта функция использует все комбинации и возвращает "A" .. "Z", "AA" .. "ZZ", "AAA" ... "ZZZ" вместо того, чтобы начинаться с "AB" и "ABC".

3 голосов
/ 02 ноября 2010

Этот код работает нормально, но я не уверен, достаточно ли он LINQ.

char[] validChars = Enumerable.Range(0, 26).Select(i => (char)('A' + i)).ToArray();
List<string> result = new List<string>();
List<string> generator = validChars.Select(ch => ch.ToString()).ToList();

int n = 1000;

while (result.Count < n)
{
    result.AddRange(generator);
    generator = generator.Take((n - result.Count) / validChars.Length + 1)
                         .SelectMany(s => validChars.Select(ch => s + ch))
                         .ToList();
}

var output = result.Take(n);
3 голосов
/ 02 ноября 2010

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

Используйте любой из рабочих IEnumerable<string> ответов (или, по крайней мере, любой, который охватывает необходимый диапазон), а затем, если вам нужно создать список с определенным количеством элементов, просто используйте:

List<string> list = GenerateSequence().Take(count).ToList();
1 голос
/ 02 ноября 2010

Попробуйте следующее .. Я использую Cross Join и Union для построения источника, а затем фильтрую запись, используя Take extension метод

char[] charArray = "ABCDEFGHIJKLMNOPQRSTUVWXYZ".ToCharArray();

List<String> MyList = new List<string>();
int n = 1000;

                      (from value1 in charArray
                       select new
                       {
                           newString = value1.ToString()
                       })
                   .Union
                   (
                       (from value1 in charArray
                        from value2 in charArray

                        select new
                        {
                            newString = string.Concat(value1, value2)
                        })
                    )
                    .Union
                    (
                        (from value1 in charArray
                         from value2 in charArray
                         from value3 in charArray

                         select new
                         {
                             newString = string.Concat(value1, value2, value3)
                         })
                     )
                     .Take(n)
                     .ToList()                         
                     .ForEach(i => MyList.Add(i.newString));

Надеюсь, это даст вам представление об использовании комбинации методов Linq, Lambda и Extension.

0 голосов
/ 02 ноября 2010

@ ДэнниЧен, вот и все. ваш код с небольшими изменениями ..

char[] validChars = Enumerable.Range(0, 26).Select(i => (char)('A' + i)).ToArray();

int n = 30;
int pointer = 0;
int pointerSec = 0;
int Deg = 0;
string prefix = string.Empty;
string prefixMore = string.Empty;
List<string> result = new List<string>();

while (n > 0)
{
    result.AddRange(validChars.Skip(pointer).Select(ch => prefix + ch).Take(n));
    if (pointer == 26)
    { 
        pointer = -1;
        Deg += 1;
        prefixMore = "" + validChars[pointerSec];
        pointerSec++;
        n++;
    }
    else
    {
        if (Deg == 0)
        {
            prefix = "" + validChars[pointer];
        }
        else
        {
            prefix = prefixMore + validChars[pointer];
        }
    }
    n--;
    pointer++;
}

это на 100% правильно.

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