0

what we need to do if we want to sort our string Array in a special form?
For example we have this:

players = new string[12] {"soccer","12","man","swim","3","woman","volleyball","12","man","baseball","13","man"};

now we want to sort Array by this form:(its just my desire order and don't have any logic)

sort = new string[4] {"swim","baseball","volleyball","soccer"}  

and finally have:

out = [{swim,3,woman},{baseball,13,man},{volleyball,12,man},{soccer,12,man}]

12
  • 4
    Sorry but I don't understand your logic here... Why not create player objects instead? Commented Jun 26, 2015 at 9:04
  • what is the logic? why swim comes before baseball? why soccer comes after baseball? Commented Jun 26, 2015 at 9:06
  • its not AI there should be some logic for creating collection Commented Jun 26, 2015 at 9:07
  • Described behaviour has nothing to do with sorting. Rather it is some kind of mapping which will work only with players array having special items order and will not work in any arbitrary case. Commented Jun 26, 2015 at 9:07
  • 1
    Please clarify your specific problem or add additional details to highlight exactly what you need. As it's currently written, it’s hard to tell exactly what you're asking. See the How to Ask page for help clarifying this question. Commented Jun 26, 2015 at 9:10

6 Answers 6

3

The other answers make a good point about creating a class to hold your data, but it can be done without it:

var ordered = Enumerable.Range(0, players.Length / 3)
.Select(i => new string[] { players[i*3], players[i*3+1], players[i*3+2] })
.OrderBy(a => Array.IndexOf(sort, a[0]))
.ToArray();

If you have sports in the players array that are not present in the sort array, you can filter them out.

var ordered = (from i in Enumerable.Range(0, players.Length / 3)
let index = Array.IndexOf(sort, players[i*3])
where index >= 0
select new string[] { players[i*3], players[i*3+1], players[i*3+2] }
).OrderBy(a => Array.IndexOf(sort, a[0])).ToArray();
Sign up to request clarification or add additional context in comments.

2 Comments

I must say, pretty interesting approach
good. but my desire Items went in last of my array. In my players list we have some another sport that we don't want show on my result. like 'Chess'.
3

You have one big string array which contains all of your player details. This is not the best solution.

Create player objects which contains all of the properties and put that in an array.

Then you can create custom sorting.

Player object:

public class Player {
     public string Type { get; set; }
     public string Gender { get; set; }
     public int AmountOfPlayers { get; set; }
     public int Order { get; set; }
}

Create your array list of Player objects:

List<Player> list = new List<Player>();
list.Add(new Player() { Type = "swim", Gender = "women", AmountOfPlayers = 3, Order = 1 });
list.Add(new Player() { Type = "soccer", Gender = "men", AmountOfPlayers = 12, Order = 4 });
list.Add(new Player() { Type = "volleyball", Gender = "men", AmountOfPlayers = 12, Order = 3 });
list.Add(new Player() { Type = "baseball", Gender = "men", AmountOfPlayers = 13, Order = 2 });

Sorting:

var sortedList = list.OrderBy(c => c.Order);

4 Comments

the sort is wrong (he has a specific sorting... swin first, soccer last)... and OrderBy isn't inplace... it returns a new sorted IEnumerable<>
@Mivaweb same as xanatos said, it's not true. Because after sorting by Type we'll not have my desire result.
List<Players> should be List<Player>
@EhsanDavoudi you can also set an extra property Order to assign the required order of your list. Eg 1 = swim, 2 = baseball, ...
2

While I would suggest the Object oriented approach as illustrated by others. However just in case due to some reservations you cannot do that then this will work.

string[] players = new string[15] {"soccer","12","man","swim","3","woman","volleyball","12","man","baseball","13","man"
    ,"chess","18","man"};
string[] sort = new string[4] {"swim","baseball","volleyball","soccer"};
string[] playersSorted= new string[sort.Length*3];
int destStartIndex = 0;
foreach(string str in sort)
{
  int sourceStartIndex = Array.IndexOf(players,str);
  Array.Copy(players, sourceStartIndex, playersSorted, destStartIndex, 3);
  destStartIndex += 3;
}

DEMO

1 Comment

Just be aware that Array.IndexOf is an O(n) operation, where n is the Length of array, if you have only a few sports it's probably fine.
1

You can try this way. First create a class out of initial string[], which can represent all the values in a format shown below:

Class Sport
{
   public string Name {get; set;}
   public int Number {get; set;}
   public string Gender {get; set;}
}

Once you have the collection as List<Sport> sportList, now you need to create a custom IComparer to do the necessary sorting:

class SportSorter : IComparer<Sport>
{           
    public int Compare(Sport x, Sport y )
    {
        int retVal = 0;            
        retVal = string.Compare(x.Name,y.Name);
        return retVal;
    }
}

Now simply you can call by using the instance of SportSorter

SportSorter ss = new SportSorter();

sportList.Sort(ss);

Please note right now I am using Name property to Sort, same can be changed in CustomSorter (IComparer) code. This is a stable version of sort as compared to OrderBy, which use QuickSort. In case you want to chain multiple sorters in different directions together then check the following response:

Sort List of Dictionary using IComparer instead of OrderBy

Also using the Sort in place of OrderBy will ensure sorting the same memory, not creating a new list as done by OrderBy

Comments

1

Code copied from Mivaweb:

public class Player {
     public string Type { get; set; }
     public string Gender { get; set; }
     public int AmountOfPlayers { get; set; }
}

Then

List<Player> list = new List<Player>();
list.Add(new Player() { Type = "swim", Gender = "women", AmountOfPlayers = 3 });

My code:

public static readonly string[] Order = new string[4] {"swim","baseball","volleyball","soccer"};

public static int OrderOf(string str)
{
    int ix = Array.IndexOf(Order, str);
    if (ix == -1)
    {
        ix = int.MaxValue;
    }
    return ix;
}

Then sort it:

list.Sort((p, q) => OrderOf(p.Type).CompareTo(OrderOf(q.Type)));

the list.Sort() is "in place", so it changes directly the list. Note that if sports different from the one in the lsit are present, they will go in the first places of the ordered list.

The OrderOf uses the Array.IndexOf to find the index of a type of sport in the Order array. Unknown types of sport go last.

Comments

1

This is not any sort actually but still if you want to process this data you can use following approach which is not good approach though.

string[,] outArray = new string[sort.Length, 3];
        for (int i = 0; i < sort.Length; i++)
        {
            int pos = Array.IndexOf(players, sort[i]);
            outArray[i, 0] = players[pos];
            outArray[i, 1] = players[pos + 1];
            outArray[i, 2] = players[pos + 2];
        }

Use objects,collections and lambda / LINQ for efficient solution and I guess all of the above answers follow the better approach.

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.