具有动态排序键级别的通用分层DataView类

时间:2017-08-22 16:54:12

标签: c# dataview sortedlist

当我们在多列上创建一个带有排序的DataView时,我们被迫在使用FindRows时指定所有列的值。

示例,如果我有:

dv1 = new DataView(tbl1, null, "Col1, Col2, Col3", DataViewRowState.CurrentRows);

使用FindRows时,我被迫为所有3列指定值。

无法检索Col1的特定值和Col2和Col3的“任何”值的所有行。

这在SortedList中是可能的,我可以在其中嵌套SortedList。因此,顶级SortedList将具有作为Col1的键,并将值作为另一个SortedList。第二级SortedList将具有作为Col2的键,并将值作为另一个SortedList。最后,第3级SortedList将具有作为Col3的键,以及对DataRows的引用。

使用这样的SortedList,可以编写方法,例如:

public DataRowView[] FindAny(object[] keys)

其中如果keys数组只包含1个键,则代码可以从键的第1级SortedList中找到第2级SortedList,然后遍历第2级和第3级SortedList并返回所有行,因为它们属于1st键。

我的问题是,是否有人已经编写了这样一个可以获取动态数量的密钥的SortedList类,并且可以使用任何DataTable / DataRow。

注意: 这个问题与表示层无关。我正在寻找一个数据处理辅助类,比如分析多个Excel工作表中的大量数据。 2.我目前不是在寻找基于LINQ的解决方案。我将来会迁移到LINQ。

感谢。

1 个答案:

答案 0 :(得分:0)

我设法编写了自己的泛型类,它实现了数据的层次视图。欢迎改进。

    public class HDataView
{
    private SortedList mapDataRows;
    int numMapLevels;

    public HDataView(DataTable tbl, string[] colNames)
    {
        object colVal = null;
        string colName = "";
        SortedList currLvlMap = null, nextLvlMap = null;
        DataRow dr1 = null;
        ArrayList arlLastLvlData;

        mapDataRows = new SortedList();
        numMapLevels = colNames.Length;

        for (int i = 0; i < tbl.Rows.Count; i++)
        {
            dr1 = tbl.Rows[i];
            currLvlMap = mapDataRows;
            for (int j = 0; j < colNames.Length; j++)
            {
                colName = colNames[j];
                colVal = dr1[colName];

                if (j == colNames.Length - 1)
                {
                    arlLastLvlData = (ArrayList)currLvlMap[colVal];
                    if (arlLastLvlData == null)
                    {
                        arlLastLvlData = new ArrayList();
                        currLvlMap[colVal] = arlLastLvlData;
                    }
                    arlLastLvlData.Add(dr1);
                }
                else
                {
                    nextLvlMap = (SortedList)currLvlMap[colVal];
                    if (nextLvlMap == null)
                    {
                        nextLvlMap = new SortedList();
                        currLvlMap[colVal] = nextLvlMap;
                    }

                    //For the next column, the current nextLvlMap will become the prevLvlMap
                    currLvlMap = nextLvlMap;
                }
            }
        }
    }

    public ArrayList FindAnyRows(object[] keys)
    {
        object keyVal = "";
        ArrayList arlDataRows = null, arlCurrRows = null;
        SortedList startLvlMap = null, currLvlMap = null, nextLvlMap = null;
        int mapLevel = 1, startLevel = 0;

        currLvlMap = mapDataRows;
        mapLevel = 1;
        for (int i = 0; i < keys.Length; i++)
        {
            keyVal = keys[i];

            if (currLvlMap == null)
            {
                break;
            }

            if (i == numMapLevels - 1)
            {
                arlDataRows = (ArrayList)currLvlMap[keyVal];
            }
            else
            {
                nextLvlMap = (SortedList)currLvlMap[keyVal];
                currLvlMap = nextLvlMap;
                mapLevel++;
            }
        }

        if (arlDataRows == null)
        {
            arlDataRows = new ArrayList();
        }

        if (keys.Length > 0 && keys.Length < numMapLevels)
        {
            if (currLvlMap != null)
            {
                startLvlMap = currLvlMap;
                startLevel = mapLevel;

                if (mapLevel == numMapLevels)
                {
                    for (int j = 0; j < startLvlMap.Count; j++)
                    {
                        arlCurrRows = (ArrayList)startLvlMap.GetByIndex(j);
                        if (arlCurrRows != null)
                        {
                            arlDataRows.AddRange(arlCurrRows);
                        }
                    }
                }
                else
                {
                    for (int i = 0; i < startLvlMap.Count; i++)
                    {
                        mapLevel = startLevel;
                        currLvlMap = startLvlMap;

                        //travel full depth of this map, for each element of this map
                        for (; mapLevel <= numMapLevels; mapLevel++)
                        {
                            if (mapLevel == numMapLevels)
                            {
                                for (int j = 0; j < currLvlMap.Count; j++)
                                {
                                    arlCurrRows = (ArrayList)currLvlMap.GetByIndex(j);
                                    if (arlCurrRows != null)
                                    {
                                        arlDataRows.AddRange(arlCurrRows);
                                    }
                                }
                            }
                            else
                            {
                                //Next level of current element of the starting map
                                nextLvlMap = (SortedList)currLvlMap.GetByIndex(i);
                                currLvlMap = nextLvlMap;
                            }
                        }
                    }
                }
            }
        }

        return arlDataRows;
    }
}