1

I have a 2D char array.

I want loop through and add each char + index in consecutive order to a new 1D list.

So the new 1D list will display as:

G0
V1
H2
F3
I4
E5
V6
A7
U8
G9
N10
L11
...

C#

char[,] array = new char[6,4] { 
    { 'G', 'V', 'H', 'F' },
    { 'I', 'E', 'V', 'A' },
    { 'U', 'G', 'N', 'L' },
    { 'G', 'X', 'F', 'W' },
    { 'E', 'N', 'L', 'H' },
    { 'A', 'H', 'V', 'B' }
};


List<string> matrixCharacters = new List<string>();


for (int m = 0; m < 24; m++) // marix positions 24
{
    for (int r = 0; r < 6; r++) // matrix rows 6
    {
        for (int c = 0; c < 4; c++) // matrix columns 4
        {
            matrixCharacters.Add(array[r,c].ToString() + r.ToString());
        }
    }
}

But I'm having trouble making a loop that can do it.

This displays:

http://rextester.com/RPRXM23687

G0
V0
H0
F0
I1
E1
V1
A1
U2
G2
N2
L2
...

Method 2 displays:

http://rextester.com/TYLJE96460

GVHF0
IEVA1
UGNL2
GXFW3
ENLH4
AHVB5
Matt McManis
  • 4,475
  • 5
  • 38
  • 93

2 Answers2

3

You can replace the loops along with having to manually create the list with a single LINQ query, this will also make the whole code more compact:

var list = array.Cast<char>().Select((c, i) => $"{c}{i}").ToList();

Let's take a look at how it works:

  • array.Cast<char>() - this flattens the 2D matrix into a linear array, or rather, it enumerates the items in the 2D array as if it was a linear array. It's useful in cases like this, where you're interested in going over each item, without having to actually create additional lists or copy the original data into another data structure.
  • Select((c, i) => $"{c}{i}") - this applies a selection function to each item in the previous sequence. Since we're calling this on the results of Cast<char>(), this will apply our function to each char in the original list. In this case, the function takes two parameters (c, i), a character and its index in the list, and returns the string $"{c}{i}". We're using string interpolation, so the values between the { } brackets will be our arguments in the lambda function. To recap, every item in the original array will be selected along with its index, and the result of this function will be a string containing the value itself, given by {c} and its index, given by {i}.
  • ToList() - this just creates a list with the resulting items from the previous query.

It's a good idea to long into the LINQ methods, as they're usually less error-prone than manual loops, in cases like this one.

A LINQ query might seem more obscure at the beginning, if you're new to C#, but in the long run it'll be well worth the effort, as it'll make you save a ton of times whenever you have to make some selection/filtering/query on a given set of items.

Sergio0694
  • 4,447
  • 3
  • 31
  • 58
  • Not as good a learning opportunity though; LINQ is pretty abstruse at the best of times. Please add some words of explanation as to HOW it works, to your answer, rather than just dumping a load of cryptic code into an answer with no explanation. We're all here to learn.. – Caius Jard Dec 13 '17 at 00:29
  • @CaiusJard Right, I've added some more insights into the answer. I just went with a LINQ query as I thought it'd be a good idea for him to get a peek into the LINQ methods from the get go. – Sergio0694 Dec 13 '17 at 00:43
  • I'm getting `Error: Unexpected character '$'` in rextester. – Matt McManis Dec 13 '17 at 00:51
  • 1
    @MattMcManis That's because that site is using an older version of C# and the $ operator isn't supported. You can just test the script with any IDE that supports C# 6.0 (any recent version of Visual Studio will work just fine) or just replace that part with `String.Format("{0}{1}", c, i)`, which is the same as the above. Basically, that $ operator is just calling the `String.Format` method for you behind the scenes. – Sergio0694 Dec 13 '17 at 01:04
  • Do always keep in mind that LINQ is a hammer that can make every problem look like a nail - I asked for clarification on this question as to how the LINQ was working it's magic and sergio0694 did some great explanation. That in itself is one f the reasons why I sometimes *avoid* LINQ - it makes code shorter but not necessarily easier to understand, maintain or debug. In this case it's unlikely to cause a problem as this is relatively simple, but overusing LINQ can make life very hard work; aim to strike a good balance – Caius Jard Dec 13 '17 at 06:50
  • (Also see https://stackoverflow.com/questions/5132397/fast-way-to-convert-a-two-dimensional-array-to-a-list-one-dimensional for an interesting discussion around relative performances - LINQ can be an incredibly inefficient way of getting the job done) – Caius Jard Dec 13 '17 at 06:57
2

Ditch (remove from your code) the first loop with 24 iterations

Make the logic of your list add:

        matrixCharacters.Add(array[r,c].ToString() + (r * 4 + c).ToString());

variable r increments from 0 to 5. For each value of r, c increments from 0 to 3. This is why r*4+c counts from 0 to 23; it's like a base 4 number:

0*4+0=0
0*4+1=1
0*4+2=2
0*4+3=3
1*4+0=4 //c back to 0, r up to 1
...
Caius Jard
  • 72,509
  • 5
  • 49
  • 80