Inverse sorting of two-dimensional array

I know this kind of question has been asked before, but I just cannot figure out how to do it...

Currently I am creating a medical application which should order diseases based on likelihood, so let's imagine this database (which I put in a 2-dim. array):

string[,] TwoDimArray =
{
    {"disease_1", "50"},
    {"disease_2", "80"},
    {"disease_3", "35" }
};

Now I want to sort the array in a way that puts disease_2 on top (because that one has 80% occurrence), then disease_1 and so on.... so it should have an inverse sorting based on the second dimension of the array.  I haven't been able to figure out how to do this, hopefully anyone can help!
pieter78Asked:
Who is Participating?
 
Babycorn-StarfishConnect With a Mentor Commented:
Hi again,

I simply 'bolted on' the IComparable Interface to your struct, this allows it to be used by the object implementing the IComparer interface.

Not sure how purists would view this, it seemed wierd using an Interface on a struct, especially one whose sole argument is of type object which is subsequently cast
to a struct. Wierd as i've not done this before, must read more .NET documentation - used to classes.

Hope this helps, just copy and paste the altered struct - it seems to work, let me know if there are futher problems.

Incidentally, just out as an aside, why a struct - not a criticism just purely, well nosy if i'm honest!

using System;
using System.Collections;

namespace ConsoleApplication3
{
      /// <summary>
      /// Summary description for Class1.
      /// </summary>
      class Class1
      {
            
            [STAThread]
            static void Main(string[] args)
            {
                  DiseaseChance[] DiseaseArray = new DiseaseChance[]{new DiseaseChance("One", 5),      new DiseaseChance("Two", 2),new DiseaseChance("Three",7)};
                  IComparer ChanceComparer = new ChanceReverserClass();
                  try
                  {
                        Array.Sort(DiseaseArray, 0, DiseaseArray.Length, ChanceComparer);                        
                  }
                  catch(Exception e)
                  {
                        Console.WriteLine(e.ToString() + "\n" + e.StackTrace);                        
                  }
            }

            
            }
      }
      public class ChanceReverserClass : IComparer  
      {
            // Calls CaseInsensitiveComparer.Compare with the parameters reversed.
            int IComparer.Compare( Object x, Object y )  
            {
                  return( (new CaseInsensitiveComparer()).Compare( y, x ) );
            }
      }

      public struct DiseaseChance : IComparable
      {
            public DiseaseChance(string disease, int chance)
            {
                  Disease = disease;
                  Chance  = chance;
            }
            public string Disease;
            public int    Chance;                
            //implementation of IComparable
            public int CompareTo(object o)
            {
                  if(o == null)
                  {
                        //the compared object is less than by default
                        return 1;
                  }
                  DiseaseChance compared = (DiseaseChance)o;
                  if(compared.Chance == this.Chance)
                  {
                        //if they are equal
                        return 0;
                  }
                  else if(compared.Chance > this.Chance)
                  {
                        //the compared object is greater than this
                        return -1;
                  }
                  else
                  {
                        //the compared object is less than
                        return 1;
                  }
            }
            
      }      

Cheers

Jay
0
 
AgariciCommented:
you should put your desease info in a struct or class
like this:
class Desease{
public string name;
public int occurence;
}

and have an array of 'Desease's sorted with a custom comparer (use this override of array sort : public static void Sort(Array, Array, IComparer); )
another way is to make the Desease class implement IComparable, htis way you do not need a custom comparer.

yet another way is to put your data in a datatable (this is specialy suitable if your data comes from a database) and sort that table by a column (or more)
this is done by setting the defaultview.sort property of the datatable to a string identifying the datacolumn to sort by
like this (suppose the table has two columns: Name and Occurence )
YourDataTable.DefaultView.Sort = "Occurence"
now this piece of code will print on the screen the sorted data:
foreach( DataRowView drv in YourDataTable.DefaultView )
{
   DataRow dr = drv.Row;
   Console.Writeline( "{0},{1}", dr["Name"], dr["Occurence"] );
}

hth,
A.
0
 
Babycorn-StarfishConnect With a Mentor Commented:
Hi,

you could create a class to represent the disease and implement the IComparable interface which an array can use to sort
e.g
class Disease : IComparable
      {
            private string name;
            private double likelihood;            

            public Disease(string name, double likelihood)
            {
                  this.name = name;
                  this.likelihood = likelihood;                  
            }

            public double getLikelihood()
            {
                  return likelihood;
            }
            //other methods here
      
                //implementation of IComparable
            public int CompareTo(object o)
            {
                  if(o == null)
                  {
                        //the compared object is less than by default
                        return 1;
                  }
                  Disease compared = (Disease)o;
                  if(compared.getLikelihood() == likelihood)
                  {
                        //if they are equal
                        return 0;
                  }
                  else if(compared.getLikelihood() > likelihood)
                  {
                        //the compared object is greater than this
                        return -1;
                  }
                  else
                  {
                        //the compared object is less than
                        return 1;
                  }
            }
      }

this will allow you to use a one dimensional array and use the static method of Array

e.g.
Assuming you have an array of type Disease called D simply pass it into Sort -> Array.Sort(D);

Hope this helps (and works!)

BCS
0
Free Tool: ZipGrep

ZipGrep is a utility that can list and search zip (.war, .ear, .jar, etc) archives for text patterns, without the need to extract the archive's contents.

One of a set of tools we're offering as a way to say thank you for being a part of the community.

 
Babycorn-StarfishCommented:
Should have refreshed before posting !!!

LOL
0
 
pieter78Author Commented:
Wow... must admit I am fairly new to C#, have some experience in PHP but not in here... Seems like a lot of work to sort just such a simple piece of code. Anyway, if this is how it must be done, I will have a try, but... no easier options? ;-)
0
 
AgariciCommented:
if your data comes from a database via an adapter and you already have it in a datatable then the simpliest way is to aply a view to that datatable.

if not... i think the simpliest way is to implement a class, the way Babycorn-Starfish did in his post.

A.
0
 
YurichCommented:
before you applied the view or anything...

if you get your data off the database (and you do since you mentioned it in your first posting), you would have some kind of an sql statement, something like:

"SELECT desease_name, desease_occurence FROM deseases"

in which case you can just try to add "ORDER BY desease_occurence DESC" and it'll be sorted in the order you'd like.

There are ways of sorting your array as well but using classes is definitely is a better approach. Yet, do you really want to keep you final result in the array or it can be an ArrayList for example?

regards

0
 
csmasterkbCommented:
I agree that you should use some sort of database sort, but if you really want to use arrays, you can:

string[,] TwoDimArray =
         {
            {"disease_1", "50"},
            {"disease_2", "80"},
            {"disease_3", "35" }
         };

         //Create one dimensional array of this array
         string[] DiseaseArray, ProbArray;
         //get the size of half the 2 dimensional array
         int ConvertedTwoDimArraySize = TwoDimArray.Length/2;
         //initiate the 1 dimensional arrays
         DiseaseArray = new string[ConvertedTwoDimArraySize];
         ProbArray = new string[ConvertedTwoDimArraySize];
            //loop through all the data from the Two Dimensional Array
         for (int i = 0;i<ConvertedTwoDimArraySize;i++)
         {
            //set the disease array to the first element (0 index based)
            DiseaseArray[i] = TwoDimArray[i,0];
            //set the probability array to the second element (0+1)
            ProbArray[i]= TwoDimArray[i,1];
         }
         
         /* Array.Sort sorts a pair of one-dimensional Array objects (one contains the keys and the other contains
          * the corresponding items) based on the keys in the first Array using the IComparable interface
          * implemented by each key.
          * Each key in the keys Array has a corresponding item in the items Array.
          * When a key is repositioned during the sorting, the corresponding item in the items Array is
          * similarly repositioned. Therefore, the items Array is sorted according to the arrangement
          * of the corresponding keys in the keys Array.
          * see http://msdn.microsoft.com/library/default.asp?url=/library/en-us/cpref/html/frlrfsystemarrayclasssorttopic2.asp
          *
          */
         //sort the array in ascending order (we will invert later)
         Array.Sort(ProbArray,DiseaseArray);
         //create a new Two Dimensional Array
         string [,] NewTwoDimArray;
         NewTwoDimArray = new string[ConvertedTwoDimArraySize,2];

         //loop through the array
         for (int i = 0;i<ConvertedTwoDimArraySize;i++)
         {
            //populate the last item (which we want first) into the 0,0 position, and so on
            //this will give us inverse sort. Since 0 index based, we have to -1
            NewTwoDimArray[i,0]=DiseaseArray[ConvertedTwoDimArraySize-1-i];
            NewTwoDimArray[i,1]=ProbArray[ConvertedTwoDimArraySize-1-i];
         }

         //Do something with the data
         for (int i = 0;i<ConvertedTwoDimArraySize;i++)
         {
            string message = NewTwoDimArray[i,0] + " has an " + NewTwoDimArray[i,1] + " chance of happening";
            Console.WriteLine(message);
         }
0
 
pieter78Author Commented:
I see things are getting complicated... I am developing this software using Crossfire, a plugin for VS.NET that permits you to develop for PDA. And... it does NOT know Array.Sort(), neither the Sort() method for an individual array. I think the first thing I am going to do is contact Appforge, the producer of the software. But any ideas remain welcome....

Yurich: I haven't been experimenting with PDA databases yet, I just called my collection of data a database, but I entered them directly in an array. This is just a demo application, and I have been working with arrays in PHP with great pleasure. And indeed, the ORDER BY ... desc is very helpful in that case.

Just don't know what direction to look in now... I thought arrays would be simple, and in fact: they work. Just the sorting....
0
 
pieter78Author Commented:
Well, I wrote Appforge, and this is what they say: "Crossfire does not provide any automatic method for sorting arrays.  If you need to sort an array, you will need to write code to perform the sort operation."  --  Thanks, Appforge... *NOT* !!

So, I must find something else, but for now I just want to stick to the array (I am not that familiar with C# that I can work with datatables and so on, that is something for later ~ besides, it is all for PDA)

I can imagine something else, which is slower and not that elegant, but it is sufficient for this application.
I am writing the Disease and the Chance to an array, and I guess you could just check whether the Chance is smaller than the chance in the line above. If so, insert the data, if not: check if it would be if you insert it one line above, and so on...

But how should I see this in code? Something like:

for (int i=0; i<ArrayLength; i++)
{
    if Chance[i] < Chance[i-1]
        {// insert data}
    else
        {// decrease i with 1 and check again}

   // then continue with next array element
}

Please help, so far C# has been really demotivating... hope time will improve things. I ordered the book from Murach, hoping that a clear explanation will help...

Thanks in advance!
0
 
pieter78Author Commented:
Okay... I have been trying some code and more... reading about it... but still there is a problem. I am working in the .NET Compact Framework (I left Crossfire for a while, then at least there is 1 standard). In the current version of the Compact Framework (1.1) there is no support for the SortedList, which would be a good suggestion. So, I went back to the IComparer, which I earlier used fo a working test app. But now I cannot get it to work....

Hope one of you guys can help me. I used a struct, and from there a normal array (so no multidim. arrays anymore... indeed too complicated). Who knows how to solve this?
(Question was: inverse sorting of Diseases by Chance)

----------------------------------------------------------------------------------------------------------------------------------
public class ChanceReverserClass : IComparer  
            {
                  // Calls CaseInsensitiveComparer.Compare with the parameters reversed.
                  int IComparer.Compare( Object x, Object y )  
                  {
                        return( (new CaseInsensitiveComparer()).Compare( y, x ) );
                  }
            }

            public struct DiseaseChance
            {
                  public DiseaseChance(string disease, int chance)
                  {
                        Disease = disease;
                        Chance  = chance;
                  }
                  public string Disease;
                  public int    Chance;
            }

            public DiseaseChance[] DiseaseArray = new DiseaseChance[]
            {
                  new DiseaseChance("One", 5),
                  new DiseaseChance("Two", 2),
                  new DiseaseChance("Three", 7)
            };

            private void Form1_Load(object sender, System.EventArgs e)
            {
                  IComparer ChanceComparer = new ChanceReverserClass();
                  Array.Sort(DiseaseArray, 0, DiseaseArray.Length, ChanceComparer);
                  // further attempts fail...
            }
----------------------------------------------------------------------------------------------------------------------------------
0
 
pieter78Author Commented:
Well, about the difference between classes and structs: I don't know yet ;-)   I followed the advice of somebody else who told me about this, and because (in general) I could understand it, I tried. Basically, it is the same like your code....  I ordered a good book about C#, for this moment I must admit my knowledge seems to be very limited (which is true, as a matter of fact).  If you say classes are better, I can change....

So one stupid question maybe, but for now I can't figure out anymore.... how do I write the results to a screen?
I couid make an array e.g. called DiseaseOrderedList and add items to it... but will that be as simple as DiseaseOrderedList.Add(o.ToString()) ?
(would be nice to combine chance with this, but not necessarily for now)
0
 
Babycorn-StarfishCommented:
Hi,

I think if you add some kind of method e.g.

//one to output to terminal
public void PrintInfo()
{
    Console.WriteLine("Disease name: " + Disease + " Disease Probability: " + Chance");
}
//one to produce a string to use in a dialog box or something
public string ToString()
{
    return ("Disease name: " + Disease + " Disease Probability: " + chance");
}

to illustrate this add the following to the method main after the sorting bit:
foreach(DiseaseChance d in DiseaseArray)
{
     d.PrintInfo();
}

>>If you say classes are better, I can change....
I'm not too sure either, that's why i asked :).
I've a book on VB.NET which explains the differences between Struct(ure)s and Classes but i've yet to do anything which makes the differences obvious; Structs are Value types, Classes(Objects thereof) are reference types.

Jay




0
 
pieter78Author Commented:
Well, I guess BCS answerd my question... at least now it works using code someone here helped me with, but he suggested exactly the same manner (independently). So in my opinion, the question I asked has been answered, so let's close this topic. If I run into problems with the implementation I will open a new one, seems fair enough...

Thanks !!
0
Question has a verified solution.

Are you are experiencing a similar issue? Get a personalized answer when you ask a related question.

Have a better answer? Share it in a comment.

All Courses

From novice to tech pro — start learning today.