Сортировка данных ANSI из массива в список С#

У меня проблема, что я действительно не могу опустить голову. Я знаю, как сортировать данные в целом, но это меня обманывает!

У меня есть список значений в массиве. Значения выглядят так:

[03;02HTransactions
[03;16HPost Transactions
[04:02HDividends
[04;16HPostDividends
[01:01H-----------------------------------------------------
[05:01H-----------------------------------------------------
[02:16HDate: Today
[02:02HTrades

Таким образом, его по существу ANSI-форматирование с экрана терминала, который я пытаюсь перестроить в список, чтобы я мог печатать его в наших тестовых журналах, поэтому он по крайней мере выглядит смутно читаемым.

Так вот как это работает в пределах первых 6 символов: [XX: YY, где XX - номер строки, а YY - номер столбца. H не имеет значения, просто форматирование.

Вот что я получил до сих пор:

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

 for (int i = 0; i <= filteredLines.Count - 1; i++)
 {
 int rowIndex = Convert.ToInt32(filteredLines[i].Substring(1, 2));
 Dictionary<int, string=""> columns = new Dictionary<int, string="">();
 foreach (string row in filteredLines)
 {
 int innerRowIndex = Convert.ToInt32(row.Substring(1, 2));
 if (innerRowIndex == rowIndex)
 {
 int columnIndex = Convert.ToInt32(filteredLines[i].Substring(4, 2));
 string value = filteredLines[i].Remove(0, 7);
 columns.Add(columnIndex, value);
 }
 }

 string columnConcatenated = "";

 for (int j = 0; j <= columns.Count; j ++ )
 {
 columnConcatenated = columnConcatenated + columns[j];
 }

 rows.Add(columnConcatenated);
 }
</int,></int,></string></string>

То, что я в основном хочу сделать, это создать строки и отсортировать их в списке на основе номера строки, чтобы он выглядел так:

--------------------------------------------
 Trades Date: Today
 Transactions Post Transactions
 Dividends Post Dividends
--------------------------------------------

мой пример не на 100% точнее, так как трудно подсчитать точные столбцы, но вы получаете идею. Они просто должны быть на одной линии в правильном порядке.

Я не могу помочь, но чувствую, что я, вероятно, не собираюсь делать это наилучшим образом. Так есть ли идеальный способ для меня достичь этого?

3 ответа

Хорошо, я бы выполнил его так:

  • Создайте простой класс POCO/class для представления записи журнала со row, column and text свойств
  • IComparable интерфейс IComparable, поэтому эти элементы можно сортировать, сначала в строке # и в столбце # второй
  • Разобрать все записи журнала и создать простой ПОКО Entry объекта для каждого
  • Используйте простой List и сортируйте его потом
  • Используйте StringBuilder для создания окончательного вывода
  • Перебирайте каждую Entry в списке, проверяя ее строку # и, возможно, введя некоторые newlines для нашего StringBuilder, если есть пробелы
  • Если мы получим Entry с номером строки, которая совпадает с предыдущей (для которой вы можете использовать временную переменную), не Entry.text строку, а вместо этого Entry.text в эту строку, в столбце, который вы хотеть


Таким образом, у нескольких людей есть некоторые решения, хотя они казались немного сложными для того, что мне было нужно. Мне удалось решить проблему самостоятельно, используя ручку и бумагу, а затем попробовать ее в визуальной студии. Вот что я сделал:

Сначала я создал список, просмотрев исходный массив, и я отсортировал и удалил дубликаты:

List<int> rowList = new List<int>();

 for (int i = 0; i <= filteredLines.Count - 1; i++)
 {
 int rowIndex = Convert.ToInt32(filteredLines[i].Substring(1, 2));
 rowList.Add(rowIndex);
 }

 rowList = rowList.Distinct().ToList<int>();
 rowList.Sort();
</int></int></int>

Затем я создал контейнер для моего окончательного списка, который будет содержать значения, затем я запустил свою процедуру сортировки, которая использует SortedList, чтобы гарантировать сортировку столбцов, прежде чем скомпоновать их:

foreach (int listRow in rowList)
 {
 SortedList<int, string=""> columnList = new SortedList<int, string="">();
 foreach(string row in filteredLines)
 {
 int rowIndex = Convert.ToInt32(row.Substring(1, 2));
 if(rowIndex==listRow)
 {
 int columnIndex = Convert.ToInt32(row.Substring(4, 2));
 string value = row.Remove(0, 7);
 if(columnList.ContainsKey(columnIndex))
 {
 columnList[columnIndex] = columnList[columnIndex] + value;
 }
 else
 {
 columnList.Add(columnIndex, value);
 }
 }
 }

 string concatenatedColumns = "";
 foreach(string col in columnList.Values)
 {
 concatenatedColumns = concatenatedColumns + col;
 }

 parsedAndSortedRows.Add(concatenatedColumns);
 }
</int,></int,>

Он отлично выполняет работу и помещает все столбцы в нужную строку, как я хотел. Спасибо за помощь всем, хотя через разные ответы я помог придумать это решение.


У вас уже есть код для разбора каждой строки, выделения ее строки, столбца и отображаемого текста. Если строки текста не являются разреженными, вы можете представить это как в основном 2D динамический массив символов, который автоматически заполняется пробелами или пустыми строками, например:

public class StringBuilderList : IList<string>
{
 readonly List<stringbuilder> list = new List<stringbuilder>();
 readonly char pad = ' ';
 const char DefaultPad = ' ';

 public StringBuilderList(char pad)
 {
 this.pad = pad;
 }

 public StringBuilderList() : this(DefaultPad) {}

 public void SetString(int iLine, int iChar, string text)
 {
 list.EnsureCount(iLine + 1);
 if (list[iLine] == null)
 list[iLine] = new StringBuilder(iChar + text.Length);
 var sb = list[iLine];
 sb.OverwriteAt(iChar, text, pad);
 }

 #region IList<string> Members

 public int IndexOf(string item)
 {
 for (int i = 0; i < Count; i++)
 if (this[i] == item) // this is not memory-efficient.
 return i;
 return -1;
 }

 public void Insert(int index, string item)
 {
 var sb = new StringBuilder(item);
 list.Insert(index, sb);
 }

 public void RemoveAt(int index)
 {
 list.RemoveAt(index);
 }

 public string this[int index]
 {
 get
 {
 // Hide the nulls from the caller!
 var sb = list[index];
 if (sb == null)
 return string.Empty;
 return sb.ToString();
 }
 set
 {
 if (string.IsNullOrEmpty(value))
 {
 if (list[index] != null)
 list[index].Length = 0;
 }
 else if (list[index] == null)
 {
 list[index] = new StringBuilder(value);
 }
 else
 {
 list[index].Length = 0;
 list[index].Append(value);
 }
 }
 }

 #endregion

 #region ICollection<string> Members

 public void Add(string item)
 {
 list.Add(new StringBuilder(item));
 }

 public void Clear()
 {
 list.Clear();
 }

 public bool Contains(string item)
 {
 return IndexOf(item) >= 0;
 }

 public void CopyTo(string[] array, int **********)
 {
 foreach (var str in this)
 array[**********++] = str;
 }

 public int Count
 {
 get { return list.Count; }
 }

 public bool IsReadOnly
 {
 get { return false; }
 }

 public bool Remove(string item)
 {
 int index = IndexOf(item);
 if (index < 0)
 return false;
 RemoveAt(index);
 return true;
 }

 #endregion

 #region IEnumerable<string> Members

 public IEnumerator<string> GetEnumerator()
 {
 foreach (var sb in list)
 yield return (sb == null ? string.Empty : sb.ToString());
 }

 #endregion

 #region IEnumerable Members

 System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator()
 {
 return GetEnumerator();
 }

 #endregion
}
</string></string></string></string></stringbuilder></stringbuilder></string>

SetString - это метод, который вы хотите использовать, он копирует строку в массив символов 2d, расширяя ее по мере необходимости пустыми строками и/или пробелами.

И вспомогательные методы:

public static class ListHelper
{
 public static void Resize<t>(this List<t> list, int count)
 {
 if (list == null || count < 0)
 throw new ArgumentException();
 int oldCount = list.Count;
 if (count > oldCount)
 {
 list.Capacity = count;
 for (int i = oldCount; i < count; i++)
 list.Add(default(T));
 }
 else if (count < oldCount)
 {
 for (int i = oldCount-1; i >= count; i--)
 list.RemoveAt(i);
 }
 }

 public static void EnsureCount<t>(this List<t> list, int count)
 {
 if (list == null || count < 0)
 throw new ArgumentException();
 if (count > list.Count)
 list.Resize(count);
 }
}

public static class StringBuilderHelper
{
 public static void OverwriteAt(this StringBuilder sb, int index, string text, char pad)
 {
 var textLen = text.Length;
 if (textLen + index > sb.Length)
 {
 for (int i = sb.Length, newLen = textLen + index; i < newLen; i++)
 {
 sb.Append(pad);
 }
 }

 for (int i = 0; i < textLen; i++)
 {
 sb[index + i] = text[i];
 }
 }
}
</t></t></t></t>

licensed under cc by-sa 3.0 with attribution.