数据排序ANSI数据从数组到列表c#

本文关键字:数据 列表 排序 ANSI 数组 | 更新日期: 2023-09-27 18:13:57

我有一个问题,我真的不明白。一般来说,我知道如何对数据进行排序,但这一项对我来说太难了!

我有一个数组中的值列表。值看起来像这样:

[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);
        }

我实际上想做的是建立行并根据行号将它们排序到一个列表中,它看起来像:

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

我的例子不是100%准确,因为很难计算确切的列数,但是你明白了。它们只需要以正确的顺序出现在同一行。

我忍不住觉得我可能不是最好的方式。那么,有没有一种理想的方法可以让我实现这个目标呢?

数据排序ANSI数据从数组到列表c#

好的,我将这样实现它:

  • 创建一个简单的POCO/类来表示一个日志条目,其属性为row, column and text
  • 实现IComparable接口,因此这些项目可以排序,在第#行和第#列
  • 解析每个日志行并为每个
  • 创建一个简单的POCO Entry对象
  • 使用简单的List<Entry>并在之后进行排序
  • 使用StringBuilder建立最终输出
  • 循环遍历列表中的每个Entry,检查它的行号,如果有间隙,可能会为StringBuilder输入一些newlines
  • 如果我们得到一个Entry的行号与前一个相同(您可以使用临时变量),不要输出换行符,而是将Entry.text附加到这行,在您想要的列

您已经有了解析每行、提取行、列和显示文本的代码。如果文本行不是稀疏的,您可以将其表示为基本上是一个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 arrayIndex)
    {
        foreach (var str in this)
            array[arrayIndex++] = 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
}

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];
        }
    }
}

所以一些人有一些解决方案,虽然他们似乎有点过于复杂的我需要的。我自己用笔和纸解决了这个问题,然后在visual studio中尝试了一下。以下是我所做的:

首先,我通过查看原始数组创建了一个列表,并对重复项进行了排序和删除:

        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();

接下来,我为我的最终列表创建了一个容器来保存这些值,然后我运行排序例程,它使用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);
        }

它很好地完成了这项工作,并按照我想要的顺序将所有列放在正确的行上。谢谢大家的帮助,虽然我是通过不同的答案来帮助想出这个解决方案的。