Сортировка данных 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.