5

I would like to know how can i sort items of a string[] according to a specific string position. For instance i want to sort the following array by the substring " - "

Input: {xx - c, xxxxx - b, yyy - a, mlllll - d}

Expected output: {yyy - a, xxxxx - b, xx - c, mlllll - d}

What i have so far is the following:

public string[] SortByStringPos(string[] arr, string str, bool ascending)
{
    if (ascending)
    {
        var result = from s in arr
                     where s.Length >= s.IndexOf(str)
                     orderby s[s.IndexOf(str)] ascending
                     select s;

        return result.ToArray();
    }
    else
    {
        var result = from s in arr
                     where s.Length >= s.IndexOf(str)
                     orderby s[s.IndexOf(str)] descending
                     select s;

        return result.ToArray();
    }
}

Can someone drop me a hint...?

3
  • It looks like you want to sort by the letter coming after -, not by the position of - which is the same in all the strings? Commented Nov 16, 2012 at 13:51
  • So what you want is the string array to be sorted, based on only the last part of the strings in it? So ignoring the first 4 characters for instance? (Or in your case, just the part behind the "-"?" Commented Nov 16, 2012 at 13:52
  • OK sorry, i was not specifing it clear enough. I want to sort all the items within the string[] where ever a given string X occurs the first time. If X doesn't exist in a item Y, then just put Y at the end of the new string[]. I hope now it's more clear...? Commented Nov 16, 2012 at 13:53

4 Answers 4

3

For a better performance and design, I recommend you use:

    public void SortByStringPos(string[] arr, string str, bool ascending)
    {
        Array.Sort(arr, new MyStrComparer("-", ascending));
    }

    class MyStrComparer : Comparer<string>
    {
        string delimiter;
        bool isAscending;

        public MyStrComparer(string aStr, bool ascending)
        {
            delimiter = aStr;
            isAscending = ascending;
        }

        public override int Compare(string x, string y)
        {
            var r = GetMySubstring(x).CompareTo(GetMySubstring(y));
            return isAscending ? r : -r;
        }

        string GetMySubstring(string str)
        {
            return str.IndexOf(delimiter) != -1 ? str.Substring(str.LastIndexOf(delimiter)) : string.Empty;
        }

    }

You can also delete the SortByStringPos method and call Array.Sort(arr, new MyStrComparer("-", ascending)); from anywhere in your code.

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

2 Comments

@oren I tested it this time. =)
@oren Please mark as answer and vote up if you're satisfied. I'm building a reputation here! =)
3
orderby x=>x.Substring(x.LastIndexOf('-'))

i guess

so you need to order it in usual manner, then you can use this, like orderBy .... thenBy

1 Comment

can you explain more specifically what are you trying to achieve
2
static void Main()
{
    var input = new[] { "xx - c", "xx - b", "yy - a", "ml - d", };
    var delimeter = "-";
    var isAscending = true;

    var res = Sort(input, delimeter, isAscending);
}

static string[] Sort(string[] input, string delimeter, bool isAscending)
{
    var withDelimeter = input.Where(p => p.Contains(delimeter));
    var withoutDelimeter = input.Except(withDelimeter);

    Func<string, string> selector = p => p.Substring(p.IndexOf(delimeter));

    return
        (
            isAscending

                ? withDelimeter.OrderBy(selector)
                    .Concat(withoutDelimeter.OrderBy(p => p))

                : withoutDelimeter.OrderByDescending(p => p)
                    .Concat(withDelimeter.OrderByDescending(selector))
        )
        .ToArray();
}

2 Comments

When a string X within input doesn't carry the delimiter in it, it will get lost...bad :-(
Fixed case for the missing delimiters :)
0

Use Substring to get the last portion of the string. LINQ queries can be constructed step by step. This reduces code repetitions (= DRY principle, Don't Repeat Yourself):

var query = arr.Where(s => s.Contains(str));
Func<string,string> sortExpr = s => s.Substring(s.IndexOf(str));
if (ascending) {
    query = query.OrderBy(sortExpr);
} else {
    query = query.OrderByDescending(sortExpr);
}
return query.ToArray();

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.