Arrays of variant data

phudgens

Member
Joined
Nov 19, 2013
Messages
19
Programming Experience
10+
I am new to this forum and somewhat new to C#. I have been tasked with porting an extensive VB.NET program to C#. The VB program uses a 2 dimensional variant array to store string, integer, and double data. I am not finding a similar array/collection in C# that can do the same thing. Everything that I've read (admittedly not a whole lot), indicates that arrays and collections can only hold data of a single type. It's important that the data remain together in a single array since it gets sorted after creation.

Which brings up another point: are there native functions/methods for multi-level sorting of multi-dimensional arrays in C#?

Thanks
Paul Hudgens
Denver
 

jmcilhinney

C# Forum Moderator
Staff member
Joined
Apr 23, 2011
Messages
3,136
Location
Sydney, Australia
Programming Experience
10+
It sounds like you're approaching this in the wrong way.

Firstly, if you're using Variant then it's VB6, not VB.NET. VB.NET uses all the same data types as C#. Variant existed in VB6 and earlier. Just like in C#, all VB.NET data types are derived from the Object class. If you wanted something that can store any data type then you declare it as Object. If you wanted a 2D array that could hold data of different types then you'd create a 2D Object array.

Most likely though, you should not be using a 2D array at all. They have their place but they should be used only to represent a genuine matrix. It sounds like that, in your case, you have multiple pieces of data that represent a single record and then you have multiple records. In that case, you should first define a type to represent a record and then you can create a 1D array or collection of that type. For example:
public class Thing
{
    public string Text { get; set; }
    public int Count { get; set; }
    public double Amount { get; set; }
}
var things = new List<Thing> { new Thing { Text = "First", Count = 1, Amount = 1.0 } };

things.Add(new Thing { Text = "Second", Count = 2, Amount = 2.0 });
You can then use the Array.Sort or List<T>.Sort methods or the LINQ OrderBy method to sort the array or collection any way you want.
 

phudgens

Member
Joined
Nov 19, 2013
Messages
19
Programming Experience
10+
Just back from vacation - thanks very much for the help - this looks more like the object oriented programming I'm trying to achieve. I did a little reading on Linq - it appears that it can do fairly complex sorting. In my case (using the sorted data shown below) the first sort would be by column 1, then by either column 3 or 4 (depending on a previously defined variable), and which may or may not be ascending, and finally by column 11. Am I correct in assuming that Linq can handle a sort like that?

Thanks,
Paul Hudgens
Denver

W1,W1D1_1,116,37,16,Y+,Y-,14C112H,Y,Reverse,1,HF
W1,W1D1_2,117,44,16,Y+,Y-,14C112H,Y,Reverse,2,HF
W1,W1D1_3,117,51,13,Y+,Y-,14C112H,Y,Reverse,3,HF
W1,W1D1_4,117,57,14,Y+,Y-,14C112H,Y,Reverse,4,HF
W1,W1D1_5,118,64,13,Z-,Y-,14C112H,Y,Reverse,5,HF
W1,W1D1_6,119,71,10,Y+,Z+,14C112H,Y,Reverse,6,HF
W1,W1D1_7,119,79,11,Y+,Y-,14C112H,Y,Reverse,7,HF
W1,W1D1_8,119,86,11,Y+,Y-,14C112H,Y,Reverse,8,HF
W1,W1D1_9,120,94,11,Z-,Y-,14C112H,Y,Reverse,9,HF
W1,W1D1_10,120,101,8,Y+,Y-,14C112H,Y,Reverse,10,HF
W1,W1D1_11,120,108,8,Y+,Y-,14C112H,Y,Reverse,11,HF
W1,W1D1_12,120,116,9,Y+,Y-,14C112H,Y,Reverse,12,HF
W1,W1D1_13,121,123,8,Y+,X-,14C112H,Y,Reverse,13,HF
W1,W1D1_14,121,131,9,Y+,Y-,14C112H,Y,Reverse,14,HF
W1,W1D1_15,121,138,10,Y+,Z-,14C112H,Y,Reverse,15,HF
W1,W1D1_16,122,146,11,Z+,Y-,14C112H,Y,Reverse,16,HF
W1,W1D1_17,122,153,12,Y+,Y-,14C112H,Y,Reverse,17,HF
 

jmcilhinney

C# Forum Moderator
Staff member
Joined
Apr 23, 2011
Messages
3,136
Location
Sydney, Australia
Programming Experience
10+
Yes, e.g.
IEnumerable<SomeType> query = list.OrderBy(item => item.Column1);

if (sortByColumn3)
{
    if (sortAscending)
    {
        query = query.ThenBy(item => item.Column3);
    }
    else
    {
        query = query.ThenByDescending(item => item.Column3);
    }
}
else
{
    if (sortAscending)
    {
        query = query.ThenBy(item => item.Column4);
    }
    else
    {
        query = query.ThenByDescending(item => item.Column4);
    }
}

var results = query.ThenBy(item => item.Column11).ToArray();
 

phudgens

Member
Joined
Nov 19, 2013
Messages
19
Programming Experience
10+
Thanks - this is very helpful.

P. Hudgens
Denver
 

phudgens

Member
Joined
Nov 19, 2013
Messages
19
Programming Experience
10+
I am finally back to my C# conversion, and have a list (37 items consisting of a mix of strings & ints), on which I now need to perform a multi-level sort. I am using the following code:
public class HFDataList
{
public string WellName { get; set; }
public string HFName { get; set; }
public int iCell { get; set; }
public int jCell { get; set; }
public int kCell { get; set; }
public string InFace { get; set; }
...
}

public
class PrimarySort
{
public PrimarySort(refList<HFDataList> HFData, bool SortByI, bool SortByJ, bool Reverse)
{
IEnumerable<HFDataList> query = HFData.OrderBy(item => item.WellName)
if (SortByI) query = query.thenby??
}
}

I am using Visual Studio Express 2013, and the "thenby" option is not available in the second statement of my sort, as was used in the example above. A lot of trial and error have not given any progress. Can anyone see what I'm doing wrong?

Thanks,
Paul Hudgens
Denver
 

jmcilhinney

C# Forum Moderator
Staff member
Joined
Apr 23, 2011
Messages
3,136
Location
Sydney, Australia
Programming Experience
10+
ThenBy is not an option because it extends IOrderedEnumerable<T>, not the IEnumerable<T> that you have declared 'query' to be. This is an example of why you should use type inference when using LINQ in particular. Change this:
IEnumerable<HFDataList> query = HFData.OrderBy(item => item.WellName);
to this:
var query = HFData.OrderBy(item => item.WellName);
and it will work. 'query' will be inferred as the correct type and ThenBy will then be available. Because IOrderEnumerable<T> extends IEnumerable<T> you will still have everythiong available that you would have plus more.

By the way, please don't post code that way. The colouring helps but it still lacks indenting, which is the most important factor in making code readable. Post your code snippets as plain text inside
 tags as I have and they will be formatted automatically, including maintaining the indenting that you copy from the IDE.
 

phudgens

Member
Joined
Nov 19, 2013
Messages
19
Programming Experience
10+
This works.

So, as I understand it, the "ThenBy" option is available only for var type lists, not for IEnumerable, or IOrderedEnumerable - is that correct?

Thanks again for the help.

Paul Hudgens
 

jmcilhinney

C# Forum Moderator
Staff member
Joined
Apr 23, 2011
Messages
3,136
Location
Sydney, Australia
Programming Experience
10+
The ThenBy and ThenByDescending methods can only be called after a call to OrderBy or OrderByDescending and thus can only be called on an IOrderdEnumerable<T>, which is what those methods return. Because your variable in post #6 had been explicitly declared as type IEnumerable<T>, even though the OrderBy method returned an IOrderdEnumerable<T>, the compiler only knew the type of that variable, not the type of the object assigned to it. It's just like assigning a Form object to an Object variable and then expecting to be able to call Show. If the variable is type Object then the compiler only knows about Object members and Show is not a member of the Object class.
 
Top Bottom