8

I want to build two-dimentional array of strings where length of one dimention is 2. Similar to this

string[,] array = new string[,]
{
    {"a", "b"},
    {"c", "d"},
    {"e", "f"},
    {"g", "h"}
}

Doing

List<string[]> list = new List<string[]>();

list.Add(new string[2] {"a", "b"});
list.Add(new string[2] {"c", "d"});
list.Add(new string[2] {"e", "f"});
list.Add(new string[2] {"g", "h"});

list.ToArray();

gives me

string[][]

but not

string[,] 

array.

Just curious, is there some trick to build dynamically

string[,] 

array somehow?

Jason Plank
  • 2,336
  • 5
  • 31
  • 40
Alexander Prokofyev
  • 33,874
  • 33
  • 95
  • 118

6 Answers6

20

You can do this.

List<KeyValuePair<string, string>>

The idea being that the Key Value Pair would mimic the array of strings you replicated.

Botz3000
  • 39,020
  • 8
  • 103
  • 127
Terrence
  • 201
  • 2
  • 2
4

Well, you could reasonably easily write an extension method to do it. Something like this (only tested very slightly):

public static T[,] ToRectangularArray<T>(this IEnumerable<T[]> source)
{
    if (!source.Any())
    {
        return new T[0,0];
    }

    int width = source.First().Length;
    if (source.Any(array => array.Length != width))
    {
         throw new ArgumentException("All elements must have the same length");
    }

    T[,] ret = new T[source.Count(), width];
    int row = 0;
    foreach (T[] array in source)
    {
       for (int col=0; col < width; col++)
       {
           ret[row, col] = array[col];
       }
       row++;
    }
    return ret;
}

It's a slight shame that the above code uses T[] as the element type. Due to generic invariance I can't currently make source IEnumerable<IEnumerable<T>> which would be nice. An alternative might be to introduce a new type parameter with a constraint:

public static T[,] ToRectangularArray<T,U>(this IEnumerable<U> source)
    where U : IEnumerable<T>

Somewhat hairy, but it should work. (Obviously the implementation needs some changes too, but the basic principle is the same.)

Jon Skeet
  • 1,421,763
  • 867
  • 9,128
  • 9,194
  • Very nice! I am still interested if it is possible to define List<> somehow to enforce it to accept only two-element string arrays? – Alexander Prokofyev Nov 13 '08 at 07:41
  • There's no way of doing this at compile time, or with List itself. There's another class (can't remember the name at the moment) which will allow you to validate entries as they're added, but that's only at execution time. – Jon Skeet Nov 13 '08 at 08:34
2

The only way to do it would be to implement the ToArray() function yourself. You could implement it within your own collection (i.e. StringTupleCollection). This could work the same as ArrayList (i.e. internal array increasing in size as needed).

However I'm not sure the advantage of [x,2] over [x][2] (or even List<string[2]> would be significant enough to warrant the effort.

You could also write a StringTupple class as:

public class StringTupple : KeyValuePair<string, string>
{
}
Jason Plank
  • 2,336
  • 5
  • 31
  • 40
Robert Wagner
  • 17,515
  • 9
  • 56
  • 72
1

You could just use a struct. I do this when comparing XML Nodes manually.

private struct XmlPair
{
    public string Name { set; get; }
    public string Value { set; get; }
}

List<XmlPair> Pairs = new List<XmlPair>();
TheJoe
  • 57
  • 10
0

KeyValuePair did not work for me when I had to retrieve the values of the checkboxes on the controller as my model.Roles list was null.

foreach (KeyValuePair<string, bool> Role in model.Roles){...}

The KeyValuePair structure doesn't have a default parameterless constructor and can't be instantiated by the model binder. I recommend a custom model class for your view that has just those properties. ASP.NET MVC 3 binding user control of type KeyValuePair to ViewModel

I found an implementation of a checkboxlist without the use of html helper at the following link CheckboxList in MVC3.0

Community
  • 1
  • 1
hagensoft
  • 1,497
  • 13
  • 13
0

This isn't possible with a List<string[]>, as the type string[,] is different from string[].

Jason Plank
  • 2,336
  • 5
  • 31
  • 40
Andrew Kennan
  • 13,947
  • 3
  • 24
  • 33