Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

I want to get pairs of first and second letters of strings with the same length (by using LINQ)

Tags:

string

c#

list

linq

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?

like image 699
Roomey Avatar asked Dec 11 '22 01:12

Roomey


2 Answers

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!

like image 115
canton7 Avatar answered Jan 22 '23 01:01

canton7


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
like image 20
Pavel Anikhouski Avatar answered Jan 22 '23 02:01

Pavel Anikhouski