0

I am relatively new to programming. I have an array of objects which isn't necessarily full (may include null rows). And I want to sort it by one of the class parameters "int moveScore". This is my array (currently holds only 32 entries)

Score[] firstPlyScore = new Score[1000];

I tried 2 things for sorting

1 In the "Score" class, i inherited "IComparable" and used the "CompareTo" method as follows

public int CompareTo(object obj)
        {
            Score x = (Score)obj;

            if (this.moveScore < x.moveScore)
                return -1;

            if (this.moveScore > x.moveScore)
                return 1;

            return 0;
        }

I called it using;

Array.Sort(firstPlyScore);

The problem is that it does sort correctly but at the end of the array. Meaning rows 0-966 are "null" and 967-999 are sorted correctly (967 with highest "int", 999 with lowest). Is there any way to fix this.

2 I also tried this

Array.Sort(firstPlyScore, delegate
    (Score x, Score y) { return x.moveScore.CompareTo(y.moveScore); });

Here the problem was that it crashed when it reached a "null" row.

Help most appreciated!

5
  • Do you want to omit the null rows? Commented Dec 11, 2013 at 19:25
  • 4
    Have you considered using a list instead of an array? That way you can easily avoid those null entries. Commented Dec 11, 2013 at 19:25
  • to mfanto - I don't want to omit the null rows. Commented Dec 11, 2013 at 19:28
  • to Jon Skeet - I don't actually now how to use lists yet (still a student) :-) Commented Dec 11, 2013 at 19:29
  • 1
    @user3092553 List<Score> scoreList = new List<Score>();, that will create an 'open-ended' collection of Score objects, in which you can Add() to. See List<T> Commented Dec 11, 2013 at 19:30

6 Answers 6

5

The default comparison behavior is for null values to be ordered before non-null values. If you want to override this behavior, a custom Comparison<Score> like in your second example would be the way to go.

delegate (Score x, Score y) {
    if (x == null)
        return y == null ? 0 : 1;
    if (y == null)
        return -1;
    return x.moveScore.CompareTo(y.moveScore);
}

This will keep the null items at the end of the array.

To sort in descending order, just swap the x and y references in the last line.

Sign up to request clarification or add additional context in comments.

3 Comments

+1 because, as much as a think arrays here are poo, this ought to work work (and it won't "lose" all the null entries).
Thanks! This actually works only it sorts them in a ascending order. How do i get it to sort descending?
@user3092553, return y.moveScore.CompareTo(x.moveScore); should do it
3
firstPlyScore = firstPlyScore
                    .Where(x => x != null)
                    .OrderByDescending(x => x.moveScore)
                    .ToArray();

7 Comments

thanks! it works but... i need the array to be 1000 for future iterations. Is it possible to keep it at 1000?
@user3092553 just add .Concat(firstPlyScore.Where(x => x == null)) after OrderByDescending. Final linq would be: firstPlyScore = firstPlyScore .Where(x => x != null) .OrderByDescending(x => x.moveScore) .Concat(firstPlyScore.Where(x => x == null)) .ToArray();
Even though this does work, the code is quite verbose and would be hard to follow. The custom comparison option, above, is a better approach.
@Xenolightning hard to follow? maybe for you. not for all.
@Xenolightning maybe, But it shows another way of doing it with Linq. So unless it is wrong , it can be thought as an answer.
|
2

You can use Linq to Entities to sort and then convert back to an array it will re-size your array to the correct length needed without null issue

 var list = firstPlyScore.OrderByDescending(x => x.MoveScore).ToList();
       //here  how you can get always  1000 array  length  as you asked  
            for (int i = list.Count-1; i < 1000; i++)
            {
                list.Add(null);  
            }
            firstPlyScore = list.ToArray();  

        }

4 Comments

since there are some entries which are null x.MoveScore will fail
Thanks for the reply but I still get a "NullReferenceException".
Adding where and changing Order to OrderByDescending makes it my answer :)
thanks! it works but... 1) i need the array sorted in an descending order. 2) I do need the array to be 1000 for future iterations
1

In the beginning of your compare method

if(obj == null) return 0;

Comments

0

The problem is that it does sort correctly but at the end of the array. Meaning rows 0-966 are "null" and 967-999 are sorted correctly (967 with highest "int", 999 with lowest). Is there any way to fix this.

If you need something, whose size can change, you are looking for a List<int>, instead of using arrays. Arrays should be used for Lists that do not change (e.g. a chess board).

The List also provides you a method called Sort.

As mentioned by others, you can also use LINQ to achieve what you seek for.

Comments

0

Do you really need to keep 1000 items in the list even if most of them are null ? I would suggest to check the logic behind it to see if you can prevent that because that's taking a lot of space for nothing.

Otherwise, 2 possibilities:

  1. Check for Obj == null in your compare function. But it might still fail if the comparing item is null

  2. Create a custom class for your score and make Icomparable (Check this link for several example about how to sort arrays

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.