Задача:
Реализовать метод, на каждой итерации которого нечетные символы строки объединяются и переносятся на ее начало, а четные переносятся на конец. "источник" Исходная строка. "count" Количество итераций.
Мой код:
public static string ShuffleChars(string s, int count)
{
string res = string.Empty;
for (int i = 0; i <= count; i++)
{
res = $"{string.Concat(s.Where((x, i) => i % 2 == 0))}{string.Concat(s.Where((x, i) => i % 2 != 0))}";
}
}
return res;
Я отсортировал строку, но я не знаю, как я могу выполнять итерации по одному и тому же значению, я пытался использовать «для», но это не работает, помогите мне, пожалуйста.
мне нужно отсортировать так:
1. "123456789"
2."135792468" первая итерация
3."159483726" вторая итерация
4."198765432" третья итерация
но если я использую цикл, в любом случае count = 2 или count = 10 он возвращает «135792468», я не знаю, почему
@RufusL хорошо, я просто редактирую свой вопрос в этот момент
Если я правильно понимаю вашу проблему, вы в значительной степени хотите делать то, что делает ваш код; перетасовать символы в нечетных позициях в начало и четных позициях в конец.
Тем не менее, вы хотите продолжать перемешивать их, сколько раз вы проходите, count
. Если вы попытаетесь просто зациклить то, что у вас есть, вы продолжите использовать исходную строку, которую вы передали, s, а затем всегда будете возвращать одно и то же значение.
Самый простой способ добиться этого — объявить выходную строку, которую вы будете продолжать назначать до тех пор, пока не выйдете из цикла. Итак, что-то вроде:
public static string ShuffleChars(string s, int count)
{
var output = s;
for(int i = 0; i < count; i++) {
output = string.Join("", output.Where((v, j) => j % 2 == 0))
+ string.Join("", output.Where((v, j) => j % 2 != 0));
}
return output;
}
Ключевым моментом здесь является то, что вы объявляете новое значение output
и инициализируете его строковым значением, которое вы передали. Затем для каждой итерации цикла вы переназначаете значение output
новому значению. Наконец, как только вы выйдете из цикла, вы вернете окончательное значение output
.
Как заявляли другие, есть и другие способы улучшить линию назначения. Лично я, вероятно, предпочитаю использовать интерполяцию строк:
output = $"{output.Where((v, j) => j % 2 == 0)}{output.Where((v, j) => j % 2 != 0)};"
Проблемы с вашим кодом:
return
изнутри цикла. Это предотвращает завершение любой итерации, кроме первой.<=
вместо <
в своем цикле. Поскольку мы начинаем с 0
, это будет повторяться count + 1
раз.i
для счетчика циклов, что и в предложении Where
, что недопустимо, поскольку они находятся в одной области.Чтобы решить эти проблемы (и использовать string.Concat
вместо string.Join
):
public static string ShuffleChars(string s, int count)
{
for (int i = 0; i < count; i++)
{
s = string.Concat(s.Where((item, index) => index % 2 == 0)) +
string.Concat(s.Where((item, index) => index % 2 != 0));
}
return s;
}
Проверка вывода:
static void Main()
{
var input = "123456789";
Console.WriteLine($"Starting input = {input}");
Console.WriteLine($"One iteration = {ShuffleChars(input, 1)}");
Console.WriteLine($"Two iterations = {ShuffleChars(input, 2)}");
Console.WriteLine($"Three iterations = {ShuffleChars(input, 3)}");
GetKeyFromUser("\nDone! Press any key to exit...");
}
Выход
У меня такая же задача, но что, если value
равно int.MaxValue
, как мы можем оптимизировать этот код для скорости и производительности? Я тоже задавала вопрос ссылка
Вы можете преобразовать string
в IEnumerable<char>
, а затем применить те же преобразования LINQ count
количество раз. Наконец, материализуйте IEnumerable<char>
в char[]
с помощью оператора ToArray, а затем преобразуйте массив обратно в string
.
public static string ShuffleChars(string s, int count)
{
IEnumerable<char> chars = s;
foreach (var _ in Enumerable.Range(0, count))
{
chars = chars
.Select((c, i) => (c, i))
.OrderBy(e => e.i % 2)
.Select(e => e.c);
}
return new String(chars.ToArray());
}
Кроме того,
string.Concat
можно использовать вместоstring.Join
, если вы не соединяете предметы в коллекции с чем-либо.