Каждый лист имеет Name
и CodeName
. По умолчанию они оба одинаковы. Однако, как только пользователь изменит название вкладки, они будут другими. Это связано с тем, что CodeName
нельзя изменить из интерфейса электронной таблицы. Требуется доступ к VBA, чтобы изменить его. Поэтому, если вы ссылаетесь на листы по их CodeName
в коде, пользователь может дать любое имя листу, и это не будет мешать вашему коду. Пример.
Name = "MySheet" CodeName = "Sheet1" (Вы можете изменить это имя в окне свойств VBE). Теперь обратитесь к листу в коде, как показано ниже.
Debug.Print Worksheets("MySheet").Name
Debug.Print Sheet1.Name
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
и т. д.). Исходный вопрос не
Это не красиво и не быстро, но работает, однострочное и 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();
Как это для однострочника?
List<string> result = new List<string>(Regex.Split(target, @"(?<=\G.{4})", RegexOptions.Singleline));
С этим регулярным выражением не имеет значения, если последний кусок меньше четырех символов, потому что он всегда смотрит только на символы, стоящие за ним.
Я уверен, что это не самое эффективное решение, но мне просто пришлось выбросить его.
Использование регулярных выражений и Linq :
List<string> groups = (from Match m in Regex.Matches(str, @"\d{4}")
select m.Value).ToList();
Я считаю, что это более читабельно, но это личное мнение. Он также может быть однострочным :).
Почему не петли? Вот что-то, что сработает очень хорошо:
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));}
В комбинации ответов 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 я бы выбрал первый вариант: это, вероятно, наиболее эффективная из возможных реализаций, очень короткая, удобочитаемая и, что важно, выдает исключение для несоответствующего ввода.
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;
}
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;
}