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

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.