?
Solved

Inverse sorting of two-dimensional array

Posted on 2005-04-27
15
Medium Priority
?
672 Views
Last Modified: 2008-01-09
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!
0
Comment
Question by:pieter78
  • 6
  • 5
  • 2
  • +2
15 Comments
 
LVL 11

Expert Comment

by:Agarici
ID: 13876067
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
 
LVL 11

Assisted Solution

by:Babycorn-Starfish
Babycorn-Starfish earned 1500 total points
ID: 13876068
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
 
LVL 11

Expert Comment

by:Babycorn-Starfish
ID: 13876076
Should have refreshed before posting !!!

LOL
0
Independent Software Vendors: We Want Your Opinion

We value your feedback.

Take our survey and automatically be enter to win anyone of the following:
Yeti Cooler, Amazon eGift Card, and Movie eGift Card!

 

Author Comment

by:pieter78
ID: 13876150
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
 
LVL 11

Expert Comment

by:Agarici
ID: 13876217
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
 
LVL 21

Expert Comment

by:Yurich
ID: 13881131
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
 

Expert Comment

by:csmasterkb
ID: 13881661
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
 

Author Comment

by:pieter78
ID: 13883752
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
 

Author Comment

by:pieter78
ID: 13893057
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
 

Author Comment

by:pieter78
ID: 13958053
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
 
LVL 11

Accepted Solution

by:
Babycorn-Starfish earned 1500 total points
ID: 13962391
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
 

Author Comment

by:pieter78
ID: 13963264
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
 
LVL 11

Expert Comment

by:Babycorn-Starfish
ID: 13963452
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
 

Author Comment

by:pieter78
ID: 13966538
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

Featured Post

New feature and membership benefit!

New feature! Upgrade and increase expert visibility of your issues with Priority Questions.

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

Introduction Although it is an old technology, serial ports are still being used by many hardware manufacturers. If you develop applications in C#, Microsoft .NET framework has SerialPort class to communicate with the serial ports.  I needed to…
High user turnover can cause old/redundant user data to consume valuable space. UserResourceCleanup was developed to address this by automatically deleting user folders when the user account is deleted.
Integration Management Part 2
Look below the covers at a subform control , and the form that is inside it. Explore properties and see how easy it is to aggregate, get statistics, and synchronize results for your data. A Microsoft Access subform is used to show relevant calcul…
Suggested Courses

864 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question