У меня есть 2 числовые строки с запятыми:
8,1,6,3,16,9,14,11,24,17,22,19 и 2,7,4,5,10,15,12,13,18,23,20,21
и мне нужно их объединить Альтернативно каждое N-е место (например, каждое 4-е место, чтобы получить)
8,1,2,7,6,3,4,5,16,9,10,15,14,11,12,13,24,17,18,23,22,19,20,21
Я уже изучил все рекомендуемые решения, но у меня ничего не получилось.
Вот мой текущий прогресс:
string result = "";
// For every index in the strings
for (int i = 0; i < JoinedWithComma1.Length || i < JoinedWithComma2.Length; i=i+2)
{
// First choose the ith character of the
// first string if it exists
if (i < JoinedWithComma1.Length)
result += JoinedWithComma1[i];
// Then choose the ith character of the
// second string if it exists
if (i < JoinedWithComma2.Length)
result += JoinedWithComma2[i];
}
Цените любую помощь.
Вы не можете полагаться на длину строк или выбирать «i-й символ», потому что не все «элементы» (читай: числа) имеют одинаковое количество символов. Вы должны разделить строки, чтобы вместо этого вы могли получить элементы из массивов результатов:
string JoinedWithComma1 = "8,1,6,3,16,9,14,11,24,17,22,19";
string JoinedWithComma2 = "2,7,4,5,10,15,12,13,18,23,20,21";
var split1 = JoinedWithComma1.Split(',');
var split2 = JoinedWithComma2.Split(',');
if (split1.Length != split2.Length)
{
// TODO: decide what you want to happen when the two strings
// have a different number of "elements".
throw new Exception("Oops!");
}
Затем вы можете легко написать цикл for
для объединения двух списков:
var merged = new List<string>();
for (int i = 0; i < split1.Length; i += 2)
{
if (i + 1 < split1.Length)
{
merged.AddRange(new[] { split1[i], split1[i + 1],
split2[i], split2[i + 1] });
}
else
{
merged.AddRange(new[] { split1[i], split2[i] });
}
}
string result = string.Join(",", merged);
Console.WriteLine(
result); // 8,1,2,7,6,3,4,5,16,9,10,15,14,11,12,13,24,17,18,23,22,19,20,21
Когда две строки имеют разное количество «элементов», мы можем определить самую большую из двух строк int Max = Math.Max(SplitWithoutComma1.Length,SplitWithoutComma2.Length);
, а затем использовать ее в цикле for for (int i = 0; i < Max; i += 2)
Если вы пишете регулярное выражение, чтобы получить пару чисел:
var r = new Regex(@"\d+,\d+");
Вы можете разбить каждую строку на последовательность пар:
var s1pairs = r.Matches(s1).Cast<Match>().Select(m => m.ToString());
var s2pairs = r.Matches(s2).Cast<Match>().Select(m => m.ToString());
И вы можете закрепить последовательности
var zipped = s1pairs.Zip(s2pairs,(a,b)=>a+","+b);
И соедините биты вместе с запятыми
var result = string.Join(",", zipped);
Как это работает?
Regex соответствует любому количеству цифр, за которыми следует запятая, за которой следует любое количество цифр.
В строке
1,2,3,4,5,6
Соответствует 3 раза:
1,2
3,4
5,6
Matches
возвращает MatchCollection
, содержащий все эти совпадения. Чтобы быть совместимым с LINQ Select
, вам нужно Cast
MatchCollection
на IEnumerable<Match>
. Это происходит потому, что MatchCollection
предшествует изобретению IEnumerable<T>
, поэтому его перечислитель возвращает object
, которые нуждаются в приведении. После превращения в IEnumerable<Match>
каждое совпадение может быть ToString
обработано Select
, создавая последовательность строк, представляющих собой пары чисел, разделенных запятой. s1pairs
фактически представляет собой набор пар чисел:
new []{ "1,2", "3,4", "5,6" }
Повторите то же самое для строки 2
Заархивируйте последовательности. Как вы могли догадаться из названия, Zip берет один из A, затем один из B, затем один из A, затем один из B, сливая их, как молния на одежде, так что две последовательности
new [] { "1,2", "3,4" }
new [] { "A,B", "C,D" }
При застегивании в конечном итоге как
new [] { "1,2,A,B", "3,4,C,D" }
И остается только соединить его вместе с запятой
"1,2,A,B,3,4,C,D"
Это не каждый 4-й символ, это каждое второе встроенное число...