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