I have 2 lists of strings
List<string> A = new List<string> { "1QWERTY", "ASDF4B2J", "C0QW", "8D" };
List<string> B = new List<string> { "GJ65SJ2", "KO21L94B", "ABF287KF2", "GPK25" };
And I want to get pairs of first and second letters of strings with the same length (by using LINQ).
Like 1Q: GJ or AS: KO.
So, I wrote this code:
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);
}
But instead of 1Q or AS using a[0] and a[1] I got some numbers.
So, result of this request is:
130: GJ
148: KO
But when I use only a[0] or a[1]:
var res = A.Join(B, a => a.Length, b => b.Length, (a, b) => new { str = a[0] + ": " + b[0] + b[1] });
I got a correct symbol, like:
1: GJ
A: KO
So, why does It works like that and how should I change my code to make it work correctly?
This is nothing to do with linq.
a[0] is a char, not a string. Perhaps confusingly, there's no addition operator defined for char: you can't add two chars together to get a string.
However, a char is implicitly convertible to the integral types, and there's an addition operator for ints. So if you do 'A' + 'B', that gets converted to 65 + 66, which is the integer 131.
Then we try and add this to a string. There is an addition operator defined between anything and a string, which works by calling ToString() on the thing that isn't a string, and then concatenating it with the string. So 131 + ": " is the same as 131.ToString() + ": ", which is the string "131: ".
When we come to add on b[0] and b[1], we do this by adding first doing "131: " + b[0]. This follows the same rules about string addition as above, so gets turned into "131: " + b[0].ToString(), which is e.g. "131: " + 'C'.ToString(), which is "131: C". Then we do the same when adding on b[1].
There are several ways to do what you want: you can do a[0].ToString() + a[1] + ": " + ... to force that first char to turn into a string. Or you can do "" + a[0] + ... to achieve the same thing. The easiest thing, though, is not to use string concatenation at all, and instead do $"{a[0]}{a[1]}: {b[0]}{b[1]}".
Another way is to not pick out individual chars, but instead of a.Substring(0, 2) to pull out the first two chars as a string. Then you can write either a.Substring(0, 2) + ": " + b.Substring(0, 2), or $"{a.Substring(0, 2)}: {b.Substring(0, 2)}"`.
Note that none of this is safe if you've got any strings which are 0 or 1 characters long!
You can simply update the result selector Func in Join method to
(a, b) => new { str = $"{a.Substring(0,2)}:{b.Substring(0,2)}" }
This will get first two letters from a and b strings and concatenate them into one string using string interpolation. Output will be the following
1Q:GJ
AS:KO
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With