Я хочу получить пары первых и вторых букв строк одинаковой длины (используя LINQ) - PullRequest
4 голосов
/ 30 января 2020

У меня есть 2 списка строк

List<string> A = new List<string> { "1QWERTY", "ASDF4B2J", "C0QW", "8D" };
List<string> B = new List<string> { "GJ65SJ2", "KO21L94B", "ABF287KF2", "GPK25" };

И я хочу получить пары первых и вторых букв строк одинаковой длины (используя LINQ).

Как 1Q: GJ или AS: KO.

Итак, я написал этот код:

var res = A.Join(
  B,
  a => a.Length,
  b => b.Length,
  (a, b) => new { str = a[0] + a[1] + ": " + b[0] + b[1] }
);

foreach (var e in res)
{
    Console.WriteLine(e.str);
}

Но вместо 1Q или AS с использованием a[0] и a[1] я получил несколько чисел .
Итак, результат этого запроса:

130: GJ
148: KO

Но когда я использую только a[0] или a[1]:

var res = A.Join(B, a => a.Length, b => b.Length, (a, b) => new { str = a[0] + ": " + b[0] + b[1] });

, я получил правильный символ, например :

1: GJ
A: KO

Итак, почему это так работает и как мне изменить свой код, чтобы он работал правильно?

Ответы [ 3 ]

7 голосов
/ 30 января 2020

Это не имеет ничего общего с linq.

a[0] - это char, а не string. Возможно, это сбивает с толку то, что для char не определен оператор сложения: вы не можете добавить два chars вместе, чтобы получить string.

Однако , char неявно преобразуются в целочисленные типы, и есть оператор сложения для ints Так что, если вы сделаете 'A' + 'B', это будет преобразовано в 65 + 66, которое является целым числом 131.

Затем мы попытаемся добавить это к string. Существует оператор сложения, определенный между чем угодно и string, который работает, вызывая ToString() для вещи, которая не является строкой, и затем объединяет ее со строкой. Так что 131 + ": " - это то же самое, что и 131.ToString() + ": ", то есть строка "131: ".

Когда мы добавим b[0] и b[1], мы сделаем это, сначала добавив "131: " + b[0] , Это следует тем же правилам добавления строк, что и выше, поэтому превращается в "131: " + b[0].ToString(), например, "131: " + 'C'.ToString(), то есть «131: C». Затем мы делаем то же самое при добавлении b[1].

. Есть несколько способов сделать то, что вы хотите: вы можете сделать a[0].ToString() + a[1] + ": " + ..., чтобы заставить первый char превратиться в string. Или вы можете сделать "" + a[0] + ..., чтобы добиться того же. Однако проще всего вообще не использовать конкатенацию строк, а вместо этого сделать $"{a[0]}{a[1]}: {b[0]}{b[1]}".

Другим способом является не выделение отдельных символов, а вместо a.Substring(0, 2) извлечение первых двух символов в виде строки. Затем вы можете написать либо a.Substring(0, 2) + ": " + b.Substring(0, 2), либо $ "{a.Substring (0, 2)}: {b.Substring (0, 2)}" `.

Обратите внимание, что ничего из этого не безопасно, если у вас есть строки длиной 0 или 1 символ!

6 голосов
/ 31 января 2020

Вы можете просто обновить селектор результатов Func в методе Join до

(a, b) => new { str = $"{a.Substring(0,2)}:{b.Substring(0,2)}" }

Это позволит получить первые две буквы из строк a и b и объединить их в одну строку, используя строковую интерполяцию . Вывод будет следующим

1Q:GJ
AS:KO
0 голосов
/ 04 февраля 2020

В вашем решении вместо строкового индекса используйте строковую подстроку следующим образом

var res = A.Join(B,
              a => a.Length,
              b => b.Length,
              (a, b) => new { str = a.Substring(0,2) + ":" + b.Substring(0,2) });
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...