Разделение строки в блоки определенного размера

Каждый лист имеет Name и CodeName. По умолчанию они оба одинаковы. Однако, как только пользователь изменит название вкладки, они будут другими. Это связано с тем, что CodeName нельзя изменить из интерфейса электронной таблицы. Требуется доступ к VBA, чтобы изменить его. Поэтому, если вы ссылаетесь на листы по их CodeName в коде, пользователь может дать любое имя листу, и это не будет мешать вашему коду. Пример.

Name = "MySheet" CodeName = "Sheet1" (Вы можете изменить это имя в окне свойств VBE). Теперь обратитесь к листу в коде, как показано ниже.

Debug.Print Worksheets("MySheet").Name
Debug.Print Sheet1.Name
199
задан Jeff Mercado 17 October 2011 в 10:43
поделиться

8 ответов

static IEnumerable<string> Split(string str, int chunkSize)
{
    return Enumerable.Range(0, str.Length / chunkSize)
        .Select(i => str.Substring(i * chunkSize, chunkSize));
}

Обратите внимание, что дополнительный код может быть требуется для корректной обработки крайних случаев ( null или пустая входная строка, chunkSize == 0 , длина входной строки не делится на chunkSize и т. д.). Исходный вопрос не

222
ответ дан 23 November 2019 в 05:07
поделиться

Это не красиво и не быстро, но работает, однострочное и LINQy:

List<string> a = text.Select((c, i) => new { Char = c, Index = i }).GroupBy(o => o.Index / 4).Select(g => new String(g.Select(o => o.Char).ToArray())).ToList();
9
ответ дан 23 November 2019 в 05:07
поделиться

Как это для однострочника?

List<string> result = new List<string>(Regex.Split(target, @"(?<=\G.{4})", RegexOptions.Singleline));

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

Я уверен, что это не самое эффективное решение, но мне просто пришлось выбросить его.

20
ответ дан 23 November 2019 в 05:07
поделиться

Использование регулярных выражений и Linq :

List<string> groups = (from Match m in Regex.Matches(str, @"\d{4}")
                       select m.Value).ToList();

Я считаю, что это более читабельно, но это личное мнение. Он также может быть однострочным :).

37
ответ дан 23 November 2019 в 05:07
поделиться

Почему не петли? Вот что-то, что сработает очень хорошо:

        string str = "111122223333444455";
        int chunkSize = 4;
        int stringLength = str.Length;
        for (int i = 0; i < stringLength ; i += chunkSize)
        {
            if (i + chunkSize > stringLength) chunkSize = stringLength  - i;
            Console.WriteLine(str.Substring(i, chunkSize));

        }
        Console.ReadLine();

Я не знаю, как вы поступите со случаем, когда строка не является множителем 4, но не сказать, что ваша идея невозможна, просто задаюсь вопросом, почему если простой цикл for делает это очень хорошо? Очевидно, что приведенное выше можно очистить и даже добавить в качестве метода расширения.

Или, как упоминалось в комментариях, вы знаете, что это / 4, затем

str = "1111222233334444";
for (int i = 0; i < stringLength; i += chunkSize) 
  {Console.WriteLine(str.Substring(i, chunkSize));} 
50
ответ дан 23 November 2019 в 05:07
поделиться

В комбинации ответов dove + Konstatin ...

static IEnumerable<string> WholeChunks(string str, int chunkSize) {
    for (int i = 0; i < str.Length; i += chunkSize) 
        yield return str.Substring(i, chunkSize);
}

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

Если вы хотите поддерживать строки любой длины, вы можете использовать следующий код:

static IEnumerable<string> ChunksUpto(string str, int maxChunkSize) {
    for (int i = 0; i < str.Length; i += maxChunkSize) 
        yield return str.Substring(i, Math.Min(maxChunkSize, str.Length-i));
}

Однако OP явно заявил, что ему не это нужно; он немного длиннее и труднее читать, немного медленнее. В духе KISS и YAGNI я бы выбрал первый вариант: это, вероятно, наиболее эффективная из возможных реализаций, очень короткая, удобочитаемая и, что важно, выдает исключение для несоответствующего ввода.

127
ответ дан 23 November 2019 в 05:07
поделиться
public static IEnumerable<IEnumerable<T>> SplitEvery<T>(this IEnumerable<T> values, int n)
{
    var ls = values.Take(n);
    var rs = values.Skip(n);
    return ls.Any() ?
        Cons(ls, SplitEvery(rs, n)) : 
        Enumerable.Empty<IEnumerable<T>>();
}

public static IEnumerable<T> Cons<T>(T x, IEnumerable<T> xs)
{
    yield return x;
    foreach (var xi in xs)
        yield return xi;
}
4
ответ дан 23 November 2019 в 05:07
поделиться
static List<string> GetChunks(string value, int chunkLength)
{
    var res = new List<string>();
    int count = (value.Length / chunkLength) + (value.Length % chunkLength > 0 ? 1 : 0);
    Enumerable.Range(0, count).ToList().ForEach(f => res.Add(value.Skip(f * chunkLength).Take(chunkLength).Select(z => z.ToString()).Aggregate((a,b) => a+b)));
    return res;
}

демо

0
ответ дан 23 November 2019 в 05:07
поделиться
Другие вопросы по тегам:

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