C#: How to order arrays in a predefined custom order by only the first 4 digits?
I want to create a simple C# GUI with a textbox in it for users to paste content into and re-copy the sorted content out.
For example the user would paste this into the box:
part # QTY
CS01-111-111 3
CS02-222-222 3
CS03-333-111 3
CS03-333-333 3
Then I want the program to sort anything pasted into it like this. Sorting by the first 4 digits only, but retaining the QTY value after it:
part # QTY
CS03-333-111 3
CS03-333-333 3
CS01-111-111 3
CS02-222-222 3
I have some C# code to help me do this, but it keeps locking up.
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
namespace WindowsFormsApplication1
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
public class Comparer : IComparer<string>
{
private Dictionary<string, int> _order;
开发者_高级运维 public Comparer()
{
_order = new Dictionary<string, int>();
_order.Add("CS01", 1);
_order.Add("CS58", 2);
_order.Add("CS11", 3);
}
public int Compare(string x, string y)
{
if (x.Length < 4 || y.Length < 4)
return x.CompareTo(y);
if (!_order.ContainsKey(x.Substring(0, 4)) || !_order.ContainsKey(y.Substring(0, 4)))
return x.CompareTo(y);
return _order[x.Substring(0, 4)].CompareTo(_order[y.Substring(0, 4)]);
}
}
private void textBox1_TextChanged(object sender, EventArgs e)
{
string[] items = textBox1.Text.Split(Environment.NewLine.ToCharArray());
Array.Sort<string>(items, 0, items.Length, new Comparer());
textBox1.Text = String.Join(Environment.NewLine, items);
}
}
}
Any ideas what I can do to fix it?
Create a comparer that contains a dictionary for how you want the strings sorted:
public class Comparer : IComparer<string> {
private Dictionary<string, int> _order;
public Comparer() {
_order = new Dictionary<string, int>();
_order.Add("03-33", 1);
_order.Add("01-11", 2);
_order.Add("02-22", 3);
}
public int Compare(string x, string y) {
return _order[x.Substring(2, 5)].CompareTo(_order[y.Substring(2, 5)]);
}
}
Then you can use the comparer in the Array.Sort
method
string[] items = TheTextBox.Text.Split(new String[]{ Environment.NewLine});
Array.Sort<string>(items, 1, items.Length - 1, new Comparer());
TheTextBox.Text = String.Join(Environment.NewLine, items);
Here are a couple of modifications to the code I posted previously.
The constructor changes may or may not work for you, but could save you some typing.
This Compare method should be almost twice as fast, because it does half as many Dictionary look-ups.
public class Comparer : IComparer<string>
{
private Dictionary<string, int> _order;
public Comparer()
{
List<string> list = new List<string>()
{
"CS01",
"CS58",
"CS11"
};
_order = new Dictionary<string, int>();
for (int i = 0; i < list.Count; i++)
{
_order.Add(list[i], i);
}
}
public int Compare(string x, string y)
{
if (x.Length < 4 || y.Length < 4)
return x.CompareTo(y);
string xPrefix = x.Substring(0, 4);
string yPrefix = y.Substring(0, 4);
int xSequence;
int ySequence;
if (_order.TryGetValue(xPrefix, out xSequence)
&& _order.TryGetValue(yPrefix, out ySequence))
{
return xSequence.CompareTo(ySequence);
}
else
{
return x.CompareTo(y);
}
}
}
It's locking up because you're changing textBox1.Text inside the textBox1_TextChanged method. So every time textBox1_TextChanged finishes, it gets called again with the new Text value.
You need something like this:
private bool _updating = false;
private void textBox1_TextChanged(object sender, EventArgs e)
{
if (!_updating)
{
try
{
_updating = true;
// do work ...
textBox1.Text = ...
}
finally
{
_updating = false;
}
}
}
or you could just check the value before you change textBox1.Text:
string newValue = ... ;
if (textBox1.Text != newValue)
{
textBox1.Text = newValue;
}
精彩评论