String Sorting Issue in C#

String sorting issue in C#

If you want your string sort to be based on the actual byte value as opposed to the rules defined by the current culture you can sort by Ordinal:

items.Sort(StringComparer.Ordinal);

This will make the results consistent across all cultures (but it will produce unintuitive sortings of "14" coming before "9" which may or may not be what you're looking for).

Default String Sort Order

Strings are always sorted in alphabetical order.

The default (string.CompareTo()) uses the Unicode comparison rules of the current culture:

    public int CompareTo(String strB) {
if (strB==null) {
return 1;
}

return CultureInfo.CurrentCulture.CompareInfo.Compare(this, strB, 0);
}

Sorting ListString in C#

How about:

    list.Sort((x, y) =>
{
int ix, iy;
return int.TryParse(x, out ix) && int.TryParse(y, out iy)
? ix.CompareTo(iy) : string.Compare(x, y);
});

How do I sort strings alphabetically while accounting for value when a string is numeric?

Pass a custom comparer into OrderBy. Enumerable.OrderBy will let you specify any comparer you like.

This is one way to do that:

void Main()
{
string[] things = new string[] { "paul", "bob", "lauren", "007", "90", "101"};

foreach (var thing in things.OrderBy(x => x, new SemiNumericComparer()))
{
Console.WriteLine(thing);
}
}

public class SemiNumericComparer: IComparer<string>
{
/// <summary>
/// Method to determine if a string is a number
/// </summary>
/// <param name="value">String to test</param>
/// <returns>True if numeric</returns>
public static bool IsNumeric(string value)
{
return int.TryParse(value, out _);
}

/// <inheritdoc />
public int Compare(string s1, string s2)
{
const int S1GreaterThanS2 = 1;
const int S2GreaterThanS1 = -1;

var IsNumeric1 = IsNumeric(s1);
var IsNumeric2 = IsNumeric(s2);

if (IsNumeric1 && IsNumeric2)
{
var i1 = Convert.ToInt32(s1);
var i2 = Convert.ToInt32(s2);

if (i1 > i2)
{
return S1GreaterThanS2;
}

if (i1 < i2)
{
return S2GreaterThanS1;
}

return 0;
}

if (IsNumeric1)
{
return S2GreaterThanS1;
}

if (IsNumeric2)
{
return S1GreaterThanS2;
}

return string.Compare(s1, s2, true, CultureInfo.InvariantCulture);
}
}

C# - Sorting Strings

The TextBox class will already give you an array of lines without any work on your part. Array.Sort will allow you to pass in your own code that compares the lines. I can't think of an elegant way to implement awkward sorting rules but the way I'd solve your problem would look something like the code below. Note that you do need to pull out the lines array into a temp variable so you can set it back, otherwise the setter isn't called and the textbox isn't updated.

private static void SortRichTextBox(RichTextBox richTextBox)
{
var lineArray = richTextBox.Lines;
Array.Sort(lineArray, delegate(string a, string b)
{
// I omitted Important corner cases like malformed lines,
// empty strings, and nulls.

// Additional sort cases can be added to the array as needed.
var sortOrder = new[] { "1111", "2222", "4444", "9999", "DDDD" };
var aTokens = a.Split(new[] { ' ' }, StringSplitOptions.RemoveEmptyEntries);
var bTokens = b.Split(new[] { ' ' }, StringSplitOptions.RemoveEmptyEntries);

var aSignifier = Array.FindIndex(sortOrder, item => aTokens[5].Contains(item));
var bSignifier = Array.FindIndex(sortOrder, item => bTokens[5].Contains(item));

// This is where your first rule is being implemented, based on the data
// from the last column. The math is unimportant, what matters is the
// return being positive vs. negative vs. zero.
if (aSignifier != bSignifier)
return aSignifier - bSignifier;

// This is where your second rule is being implemented, as a backup when
// the result from the first rule indicates equality. We're just falling
// through to ordinary string comparison on the second column.
return aTokens[1].CompareTo(bTokens[1]);
});

// We want to call the setter to get the textbox to update.
richTextBox.Lines = lineArray;
}

I tested this, and it looks like it works, at least with your one sample data set.



Related Topics



Leave a reply



Submit