tags:

views:

407

answers:

4

I have the following array:

private int[,] testSamples = new testSamples[101,101];

It's supposed to represent a roster, with column 0 to 100 and row 0 to 100. In this rosters, various chemical liquids are dropped. The person I'm doing this for wants to work in such a way that he can take care of the container with the most liquid in it first.

So, I need to get the data out and printed in this manner:

testSamples[35,40] = 12
testSamples[11,12] = 11
testSamples[92,14] = 10
testSamples[18,3] = 10
testSamples[1,61] = 7
...

For instance. I've been cracking my head over this for a few days, I've looked into some other questions here on StackoverFlow, but I can't get any of them to work.

Is there a way to do this, or should I give up on arrays and go for another sort of container, like ArrayLists or List items?

+2  A: 

You probably would be better off using something like a OrderedBag. Also, you might want to have your List store something other than simply Integers. It looks like there is a more complicated logical object that you are trying to represent, like a Roster, Experiment, Beaker, or something.

Update: Edited based on comments regarding SortedList to use an OrderedBag instead.

Nick
`SortedList` would require keys to be unique; I don't think that can be applied in this scenario.
Dan Tao
Good point. Updated to use OrderedBag instead.
Nick
+5  A: 

You can do this, but you need a container to hold the output pairs of indices, a quick way to do this is an anonymous type and LINQ:

var sorted = from x in Enumerable.Range(0, testSamples.GetLength(0))
             from y in Enumerable.Range(0, testSamples.GetLength(1))
             select new {
                X = x,
                Y = y,
                Value = testSamples[x,y]
             } into point
             orderby point.Value descending
             select point;

After this sorted is an IEnumerable of the anonymous type each being the indices and value from the array.

EDIT: Put the largest first...

Richard
@MichaelHaren: Good point... will update.
Richard
Hmz, Could it be possible to put this into a StringBuilder object? I mean, the final result.
WebDevHobo
With a StringBuilder, I could do AppendLine, toString() the final result and it could go into a textfile.Sorry if I seem to depend on you guys a bit too much, but I've never worked with LINQ or IEnumerable before. I can't find any method to make this result into a string.
WebDevHobo
@WebDevHobo: I would expect you to iterate over the contents of sorted (`foreach(var item in sorted) {...}`) In this loop you would see each ordered item and are free to do (almost) anything with them. Writing to a file or a string builder included.
Richard
A: 

Let's assume 3x3:

5 4 3
2 1 9
8 7 6

You can just store the coordinates in a SortedDictionary with key liquid size, value coordinate:

key - value
9 - [2,1]
8 - [0,3]
...
Carra
Good for sorted reading but not good for writing a new liquid amount to coordinate x,y.
Jonas Elfström
+1  A: 

Here's a suggestion that I think ends up being quite similar to Richard's, but without using LINQ.

Write a quick struct (something like this may even exist already) that includes three values: x, y, and value. Like this:

public struct SampleSlot : IComparable<SampleSlot> {
    public int X;
    public int Y;
    public int Value;

    public SampleSlot(int x, int y, int value) {
        X = x;
        Y = y;
        Value = value;
    }

    public int CompareTo(SampleSlot other) {
        return Value.CompareTo(other.Value);
    }
}

Then you can collapse your int[,] array into any sortable one-dimensional collection of SampleSlot objects you like; I'd probably go with a List<SampleSlot>:

List<SampleSlot> slotsList = new List<SampleSlot>();

for (int i = 0; i < testSamples.GetLength(0); ++i) {
    for (int j = 0; j < testSamples.GetLength(1); ++j) {
        slotsList.Add(new SampleSlot(i, j, testSamples[i, j]));
    }
}

slotsList.Sort();

// assuming you want your output in descending order
for (int i = slotsList.Count - 1; i >= 0; --i) {
    SampleSlot slot = slotsList[i];
    Console.WriteLine("testSamples[{0},{1}] = {2}", slot.X, slot.Y, slot.Value);
}
Dan Tao
It works, but it takes a good minute or so for the output to be computed.
WebDevHobo
Time-problem solved: added an if statement inside the double for-loop. If the testSamples[i;j] value is 0, don't add.
WebDevHobo