简体   繁体   中英

Sort string list dependent on some conditions in c# with linq

I've a list like this:

public static List<List<string>> GraphLists = new List<List<string>>();

It contains some data:

在此处输入图片说明

I want to sort these by SECOND item. So, list should be like this:

{0-0-44,25}
{1-0-41}
{0-1-28}
{1-1-33}
{0-2-37,33}
{1-2-44,33}

How can I do this with linq?

Quite a dirty hack i suppose, but it should give you an idea (of how I'd do it):

first of all create a little dummy class like this

class Item
{
    public string first { get; set; }
    public string second { get; set; }
    public string third { get; set; }
}

and then

List<string> list = new List<string>();
list.Add("0-0-44,25");
list.Add("1-0-41");
list.Add("0-1-28");
list.Add("1-1-33");
list.Add("0-2-37,33");
list.Add("1-2-44,33");

List<Item> items = new List<Item>();

foreach (var item in list)
{
    // split all of your strings and put it into the item class and then add it to the list
    string[] parts = item.Split('-');

    items.Add(new Item()
    {
        first = parts[0],
        second = parts[1],
        third = parts[2]
    });
}

// now you're able to sort it (by the second property)
var result = items.OrderBy(x => x.second);

List<string> resultList = new List<string>();

// and now put it back together
foreach (var item in result)
{
    resultList.Add(string.Format("{0}-{1}-{2}", item.first, item.second, item.third));
}

All you have to do now is insert back the received list.

Since you need to order by the second number in the text you need to do a Split so
Here's how I would do it:

//order the outer list based on the middle item
var orderedList = GraphLists.OrderBy(x=>x.First().Split('-')[1]);

alternative (more accurate) solution:

//order the inner lists based on the middle item
GraphLists.ForEach(innerList=>innerList.OrderBy(x=>x.First().Split('-')[1]);

There's been a lot of interpretation been going on in the question's comments. So I tell you what I understand now:

You have a list GraphList where each item is a list of strings. One string can look like this:

"0-1-44,33"

or generically

"x-y-z"

with z being a decimal number.

Now you want each of these "item lists" (elements of GraphList ) to be sorted by the second component ( y ) of the string. However, your desired result shows that you want to order by y first and then by x , so the solution presented in my original answer gives the hint:

You get a sorted "item list" by

var subList = GraphList.Items[i].OrderBy(x => 
              {
                  var split = x.Split('-');
                  return split[1].PadLeft(5, '0') + split[0].PadLeft(5, '0');
              });

I've used the following sample code to change GraphList to only contain sorted sub-lists:

    static void Main(string[] args)
    {
        List<List<string>> GraphList = new List<List<string>>();
        GraphList.Add(new List<string>() { "0-2-37", "0-0-44", "0-1-28", "1-0-41", "1-2-44", "1-1-33" });
        GraphList.Add(new List<string>() { "2-2-37", "2-0-44", "2-1-28", "3-0-41", "3-2-44", "3-1-33" });
        GraphList.Add(new List<string>() { "4-2-37", "4-0-44", "4-1-28", "5-0-41", "5-2-44", "5-1-33" });

        for (int i = 0; i < GraphList.Count; i++)
        {
            GraphList[i] = GraphList[i].OrderBy(x =>
            {
                var split = x.Split('-');
                return split[1].PadLeft(5, '0') + split[0].PadLeft(5, '0');
            }).ToList();
        }

OLD ANSWER

I would do this:

var z = l.OrderBy(x => x.First().Substring(2, 1) + x.First().Substring(0, 1));

This orders the list l by the character after the first - concatenated with the first character of the first item in each sub-list.

In your example, the list is ordered by

00
01
10
11
20
21

Please note that this assumes that there's only just one digit at every position.

If you need more than one digit, you can adapt this to use String.Split and String.PadLeft to generate fixed size sort criteria. In the following example I pad to a width of 5 digits, so it sorts by:

0000000000
0000000001
0000100000
0000100001
0000200000
0000200001

This can be achieved by:

var z = l.OrderBy(x => 
        {
            var split = x.First().Split('-');
            return split[1].PadLeft(5, '0') + split[0].PadLeft(5, '0');
        });

Take care that each list has to contain at least one element:

GraphLists.OrderBy(x => x.First());

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM