我如何处理这样的排序

时间:2018-04-12 17:04:03

标签: c# vb.net

 1
  14
    141
        141010
        141020
        141030
        141040
        141050
        141060
    142
        142010
        142020
    144
        1440
          144010
          144020
          144030
          144040  

目前,对于一个学校项目,我必须根据相似的数字制作一个阵列。

任何长度为1-2-3-4的数字都可以有孩子。

但是我无法想象如何以编程方式解决这个问题,因为当这个场景中的数字1440不存在时144010~必须将自己排序在144以下并且如果144不存在它会低于14但是保持在数字之下从142开始。

对我如何解决这个问题的任何帮助都将受到高度赞赏。

编辑:

我试过的一些代码:

 Public Class DataSet
        Public Property one As Integer
        Public Property two As New List(Of Two)
        Public Property three As New List(Of three)
        Public Property four As New List(Of four)
    End Class

    Public Class Two
        Public Property two As Integer
        Public Property three As New List(Of three)
    End Class

    Public Class three
        Public Property three As Integer
        Public Property four As New List(Of four)
    End Class

    Public Class four
        Public Property four As Integer
        Public Property six As New List(Of String)
    End Class

    Sub Main()
        Dim ds As New List(Of DataSet)
        Dim one As New List(Of String)
        Dim two As New List(Of String)
        Dim three As New List(Of String)
        Dim three_found As New List(Of String)
        Dim four As New List(Of String)
        Dim six As New List(Of String)
        Dim words() As String = File.ReadAllLines("Numbers.txt")
        For Each w In words
            Dim length = w.Length
            Dim number = Convert.ToInt32(w)
            Select Case length
                Case 1
                    one.Add(w)
                Case 2
                    two.Add(w)
                Case 3
                    three.Add(w)
                Case 4
                    four.Add(w)
                Case 6
                    six.Add(w)
            End Select
        Next

        For Each i In one
            Dim dso As New DataSet
            dso.one = i
            For Each t In two
                If t.StartsWith(i.ToString()) Then
                    Dim newtwo = New Two
                    newtwo.two = t
                    dso.two.Add(newtwo)
                End If
                For Each th In three
                    If th.StartsWith(i) Then
                        three_found.Add(th)
                        Dim twoc = th.Substring(0, 2)
                        If twoc.StartsWith(t) Then
                            Dim threec As New three
                            threec.three = th
                            Dim threef = dso.two.Where(Function(w) w.two = twoc).FirstOrDefault()
                            If threef IsNot Nothing Then
                                threef.three.Add(threec)
                            Else
                                dso.three.Add(threec)
                            End If
                        End If
                    End If
                Next
            Next        
            ds.Add(dso)
        Next

    End Sub

3 个答案:

答案 0 :(得分:0)

正如我在检查Treeview之前所说的那样。它已经为你做了这种类型的层次结构。

此代码在C#中,但您可以轻松转换为VB(手动或使用Telerik的在线转换器并进行编辑):

void Main()
{
    string values = @"1
  14
    141
        141010
        141020
        141030
        141040
        141050
        141060
    142
        142010
        142020
    144
       1440
          144010
          144020
          144030
          144040
    145020
    145030
    145010
          ";

    int myValue;
    var myData = values.Split("\r\n".ToCharArray(), StringSplitOptions.RemoveEmptyEntries)
        .Select(s => int.TryParse(s.Trim(), out myValue)?myValue:-1)
        .Where(n => n != -1);

    Func<int, IEnumerable<int>, int?> parent = (value, list) =>
    {
        while (value > 0)
        {
            value /= 10;
            if (list.Any(l => l == value))
            {
                return value;
            }
        }
        return null;
    };

    var nodes = myData
        .Select(d => new { d, parentNode = parent(d, myData) })
        .OrderBy(d => d.parentNode)
        .ThenBy(d => d.d);

    TreeView tv = new TreeView();
    foreach (var n in nodes)
    {
        var v = n.d.ToString();
        ((n.parentNode == null)
        ? tv.Nodes
        : tv.Nodes.Find("_" + n.parentNode.ToString(), true).First().Nodes)
        .Add("_" + v, v);
    }

    foreach (TreeNode node in tv.Nodes)
    {
        WriteNode(node, 0);
    }
}

private void WriteNode(TreeNode node, int level)
{
    Console.WriteLine("".PadLeft(level, '\t') + node.Text);
    foreach (TreeNode n in node.Nodes)
    {
        WriteNode(n, level + 1);
    }
}

输出结果为:

1
  14
    141
      141010
      141020
      141030
      141040
      141050
      141060
    142
      142010
      142020
    144
      1440
        144010
        144020
        144030
        144040
    145010
    145020
    145030

注意:如果您不想使用Treeview,请使用如下逻辑:

  • 创建一个列表,
  • 循环你的价值观,
  • 对于每个值,将值作为字符串
  • 获取
  • 循环从长度朝向0开始并获取子串,(比如值为144010)
  • 检查该子字符串是否存在,(您会找到1440)
  • 如果它的值前缀为该值加上分隔符(1440 \ 144010)
  • 现在继续使用新的父级(1440)进行搜索,
  • 追加任何“父母”(最终将成为1/14/144/1440/144010)
  • 将此添加到您在顶部的列表中。
  • 对列表进行排序(因为目录类似结构,所有值都会找到它们的位置)。
  • 您可以通过分隔符的数量或最后一个分隔符后的值(如目录结构中的最后一个文件夹名称)缩进您的值。

答案 1 :(得分:0)

以下是如何在不使用Treeview的情况下完成此操作(为什么我不知道):

void Main()
{
    string values = @"1
  14
    141
        141010
        141020
        141030
        141040
        141050
        141060
    142
        142010
        142020
    144
       1440
          144010
          144020
          144030
          144040
    145020
    145030
    145010
          ";

    int myValue;
// Splitting and converting to a collection of integers ordered by randomly
// just to show initial order doesn't matter
    var myData = values.Split("\r\n".ToCharArray(), StringSplitOptions.RemoveEmptyEntries)
        .Select(s => int.TryParse(s.Trim(), out myValue) ? myValue : -1)
        .Where(n => n != -1)
        .OrderBy(n => Guid.NewGuid());

// We have the collection. Sort it "directory" style
    List<string> myList = new List<string>();
    var list = myData.Select(d => d.ToString());
    foreach (var v in myData)
    {
        myList.Add(Fullpath(v.ToString(), list));
    }
    var ordered = myList.OrderBy(l => l);
// Write out the result intended
    foreach (var element in ordered)
    {
        var levels = element.Count(e => e == '/');
        var value = levels > 0 ? element.Remove(0, element.LastIndexOf('/') + 1) : element;
        Console.WriteLine("".PadLeft(levels, '\t') + value);
    }
}

// Get the full path for a value with ancestors
// ie: 1/14/1440/144010 is the full path for 144010
private string Fullpath(string key, IEnumerable<string> list)
{
    List<string> paths = new List<string>();
    for (int i = 1; i <= key.Length; i++)
    {
        if (list.Any(v => key.Substring(0, i) == v))
        {
            paths.Add(key.Substring(0, i));
        }
    }
    return string.Join("/", paths);
}

请注意,在开始排序之前,值会被洗牌,这就是你得到的:

1
  14
    141
      141010
      141020
      141030
      141040
      141050
      141060
    142
      142010
      142020
    144
      1440
        144010
        144020
        144030
        144040
    145010
    145020
    145030

答案 2 :(得分:0)

这是VB版本(警告:我不使用VB并且不知道它,使用Telerik转换器并稍微修改以使其工作,因为VB.Net缺少文字,如&# 34; \ t&#34;我使用4个空格来打算 - 不想添加VisualBasic命名空间):

Private Sub Main()
    Dim values As String = <values>
1
  14
    141
        141010
        141020
        141030
        141040
        141050
        141060
    142
        142010
        142020
    144
       1440
          144010
          144020
          144030
          144040
    145020
    145030
    145010
</values>

' Splitting and converting to a collection of integers ordered by randomly
' just to show initial order does not matter
    Dim myValue As Integer
    Dim myData = values _
        .Split(Environment.NewLine.ToCharArray(), StringSplitOptions.RemoveEmptyEntries) _
        .Select(Function(s) If(Integer.TryParse(s.Trim(), myValue), myValue, -1)) _
        .Where(Function(n) n <> -1) _
        .OrderBy(Function(n) Guid.NewGuid())

' We have the collection. Sort it "directory" style
    Dim myList As List(Of String) = New List(Of String)()
    Dim list = myData.Select(Function(d) d.ToString())
    For Each v In myData
        myList.Add(Fullpath(v.ToString(), list))
    Next

' Write out the result intended
    Dim ordered = myList.OrderBy(Function(l) l)
    For Each element In ordered
        Dim levels = element.Count(Function(e) e = "/"c)
        Dim value = If(levels > 0, element.Remove(0, element.LastIndexOf("/"c) + 1), element)
        Console.WriteLine("".PadLeft(levels * 4, " ") + value)
    Next
End Sub

' Get the full path for a value with ancestors
' ie: 1/14/1440/144010 is the full path for 144010
Private Function Fullpath(ByVal key As String, ByVal list As IEnumerable(Of String)) As String
    Dim paths As List(Of String) = New List(Of String)()
    For i As Integer = 1 To key.Length
        If list.Any(Function(v) key.Substring(0, i) = v) Then
            paths.Add(key.Substring(0, i))
        End If
    Next

    Return String.Join("/", paths)
End Function

'=======================================================
'Service provided by Telerik (www.telerik.com)
'Conversion powered by Refactoring Essentials.
'Twitter: @telerik
'Facebook: facebook.com/telerik
'=======================================================