andrey.shedko
andrey.shedko

Reputation: 3238

Iterate and select over two dimensional string array with LINQ

I did console application that must iterate over two dimensional array of strings and select values that contains in user input and show these values in set by "row". Unfortunately I got error System.Collections.Generic.List '1[System.String] Here is the code of application:

static void Main(string[] args)
{
    string[,] words = new string[,] 
    { 
        { "5", "" }, 
        { "10", "kare" },  
        { "20", "kanojo" },  
        { "1", "karetachi" },  
        { "7", "korosu" },  
        { "3", "sakura" },  
        { "3", "" }  
    };
    try
    {
        var pre = Console.ReadLine();
        var r = Enumerable
            .Range(0, words.GetLength(0))
            .Where(i => words[i, 1] == pre)
            .Select(i => words[i, 1])
            .OrderBy(i => words[Int32.Parse(i), 0])
            .ToList();
        Console.Write(r);
    }
    catch (Exception ex)
    {
        TextWriter errorWriter = Console.Error;
        errorWriter.WriteLine(ex.Message);
    }
    Console.ReadLine();
}

Upvotes: 1

Views: 1770

Answers (3)

maserlin
maserlin

Reputation: 1

The following code creates a 2D List as though we had this myList[][], consisting of [0] = {0,1,2,3} and [1] = {4,5,6,7,8}

List<List<int>> a2DList = new List<List<int>>()
{
    new List<int>()
    {
        0,1,2,3
    },
    new List<int>()
    {
        4,5,6,7,8
    }
};

The LINQ code a2DList.SelectMany(s => s).ToArray().Select(s => s)) returns a copy of the 2d array flattened into 1D form. SelectMany takes each element and projects each member of each element sequentially.

You could then say


var myObj = a2DList.SelectMany(s => s).ToArray().Select(s => s));

IEnumerable myEnumerable = a2DList.SelectMany(s => s).ToArray().Select(s => s));

int [] myArray = a2DList.SelectMany(s => s).ToArray().Select(s => s)).ToArray();

List myList = a2DList.SelectMany(s => s).ToArray().Select(s => s)).ToList();

etc

This is "join"ed by the string operator for printing out to Console

Console.WriteLine(string.Join(",",a2DList.SelectMany(s => s).ToArray().Select(s => s)));

// Output will be "0,1,2,3,4,5,6,7,8"

Upvotes: 0

Sergey Kalinichenko
Sergey Kalinichenko

Reputation: 726609

Your query is incorrect: you try to match each word from the list to the entirety of the user input, which means that you would always pick a single word (assuming there's no duplicates in the 2D array). Since you are sorting the results, however, it appears that you expect there to be more than one word.

To fix this, replace your selection criteria to use Contains, like this:

var r = Enumerable
    .Range(0, words.GetLength(0))
    .Where(i => pre.Contains(words[i, 1]))
    .Select(i => new {i, w=words[i, 1]})
    .OrderBy(p => Int32.Parse(words[p.i, 0]))
    .Select(p=>p.w)
    .ToList();

To display the results in a single line you could use string.Join:

Console.WriteLine("Results: {0}", string.Join(", ", r));

Note: I assume that the exercise requires you to use a 2D array. If there is no such requirement, you could use an array of tuples or anonymous types, letting you avoid parsing of the integer:

var words = new[] { 
    new { Priority = 5,  Word = "" }
,   new { Priority = 10, Word = "kare" }
,   new { Priority = 20, Word = "kanojo" }
,   ... // and so on
};

Demo.

Upvotes: 1

Nathan
Nathan

Reputation: 6216

That's not an error, that's what happens when you display the result of calling the ToString function of a List.

(i.e. your statement ran correctly, you just aren't displaying it the way you think.... see?)

Try:

Console.Write(r.Aggregate((a,b) => a + "," + b));

instead of

Console.Write(r);

Upvotes: 1

Related Questions