×

Loading...
Ad by
  • 推荐 OXIO 加拿大高速网络,最低月费仅$40. 使用推荐码 RCR37MB 可获得一个月的免费服务
Ad by
  • 推荐 OXIO 加拿大高速网络,最低月费仅$40. 使用推荐码 RCR37MB 可获得一个月的免费服务

玩出点乐趣,再改进一下。

本文发表在 rolia.net 枫下论坛Imports System.Linq

Public Class Class4

Public Sub AAA()
Dim myDS As DataSet = createTestDS()

Dim Xe As IEnumerable(Of XElement) = _
From Item In ( _
From E In myDS.Tables(0) _
Where ( _
From D In myDS.Tables(0) Where E("Parent") = D("Child") Select D _
).Count = 0 _
Select E("Parent") Distinct) _
Select Recursion(Item, myDS.Tables(0))

Dim strHtml As String = ""
For Each item In Xe
strHtml += item.ToString
Next
MsgBox(strHtml)


End Sub


Private Function Recursion(ByVal Name As String, ByVal DT As DataTable) As XElement

Dim myParentElement As XElement = _
<ul>
<li>
<%= Name %>
<%= From E In DT Where E("Parent") = Name Select Recursion(E("Child"), DT) %>
</li>
</ul>

Return myParentElement

End Function

Private Function createTestDS() As DataSet
Dim myDS As New DataSet
Dim myTB As New DataTable
Dim myCol As DataColumn
myCol = New DataColumn("Parent")
myTB.Columns.Add(myCol)
myCol = New DataColumn("Child")
myTB.Columns.Add(myCol)
myDS.Tables.Add(myTB)

Dim myDR As DataRow

'king(jones)
myDR = myTB.NewRow
myDR(0) = "king"
myDR(1) = "jones"
myTB.Rows.Add(myDR)
'jones(scott)
myDR = myTB.NewRow
myDR(0) = "jones"
myDR(1) = "scott"
myTB.Rows.Add(myDR)
'scott(adams)
myDR = myTB.NewRow
myDR(0) = "scott"
myDR(1) = "adams"
myTB.Rows.Add(myDR)
'jones(ford)
myDR = myTB.NewRow
myDR(0) = "jones"
myDR(1) = "ford"
myTB.Rows.Add(myDR)
'ford(smith)
myDR = myTB.NewRow
myDR(0) = "ford"
myDR(1) = "smith"
myTB.Rows.Add(myDR)
'king(blake)
myDR = myTB.NewRow
myDR(0) = "king"
myDR(1) = "blake"
myTB.Rows.Add(myDR)
'blake(allen)
myDR = myTB.NewRow
myDR(0) = "blake"
myDR(1) = "allen"
myTB.Rows.Add(myDR)
'blake(ward)
myDR = myTB.NewRow
myDR(0) = "blake"
myDR(1) = "ward"
myTB.Rows.Add(myDR)
'king(clark)
myDR = myTB.NewRow
myDR(0) = "king"
myDR(1) = "clark"
myTB.Rows.Add(myDR)
'clark(miller)
myDR = myTB.NewRow
myDR(0) = "clark"
myDR(1) = "miller"
myTB.Rows.Add(myDR)

Return myDS
End Function

End Class更多精彩文章及讨论,请光临枫下论坛 rolia.net
Report

Replies, comments and Discussions:

  • 工作学习 / 学科技术讨论 / 我这个LINQ如何?
    本文发表在 rolia.net 枫下论坛为方便加了个根单元(Root)。


    Imports System.Linq

    Imports System.Data.SqlClient
    Public Class Class4

    Public Sub AAA()
    Dim myDS As DataSet = createTestDS()

    Dim i As Integer
    Dim Xe As New XElement("Root")

    Dim myName As String
    Dim myArrayList As New ArrayList

    For i = 0 To myDS.Tables(0).Rows.Count - 1
    myName = CStr(myDS.Tables(0).Rows(i)("Parent"))
    If HasParent(myName, myDS.Tables(0)) = False AndAlso _
    Not myArrayList.Contains(myName) Then
    myArrayList.Add(myName)
    Xe.Add(Recursion(CStr(myDS.Tables(0).Rows(i)("Parent")), myDS.Tables(0)))
    End If

    Next

    MsgBox(Xe.ToString)

    End Sub

    Private Function HasParent(ByVal name As String, ByVal DT As DataTable) As Boolean
    Dim i As Integer
    For i = 0 To DT.Rows.Count - 1
    If CStr(DT.Rows(i)("Child")) = name Then
    Return True
    End If
    Next
    Return False
    End Function


    Private Function Recursion(ByVal Name As String, ByVal DT As DataTable) As XElement

    Dim myParentElement As XElement = _
    <ul>
    <li>
    <%= Name %>
    <%= From E In DT Where E("Parent") = Name Select Recursion(E("Child"), DT) %>
    </li>
    </ul>

    Return myParentElement

    End Function

    Private Function createTestDS() As DataSet
    Dim myDS As New DataSet
    Dim myTB As New DataTable
    Dim myCol As DataColumn
    myCol = New DataColumn("Parent")
    myTB.Columns.Add(myCol)
    myCol = New DataColumn("Child")
    myTB.Columns.Add(myCol)
    myDS.Tables.Add(myTB)

    Dim myDR As DataRow

    'king(jones)
    myDR = myTB.NewRow
    myDR(0) = "king"
    myDR(1) = "jones"
    myTB.Rows.Add(myDR)
    'jones(scott)
    myDR = myTB.NewRow
    myDR(0) = "jones"
    myDR(1) = "scott"
    myTB.Rows.Add(myDR)
    'scott(adams)
    myDR = myTB.NewRow
    myDR(0) = "scott"
    myDR(1) = "adams"
    myTB.Rows.Add(myDR)
    'jones(ford)
    myDR = myTB.NewRow
    myDR(0) = "jones"
    myDR(1) = "ford"
    myTB.Rows.Add(myDR)
    'ford(smith)
    myDR = myTB.NewRow
    myDR(0) = "ford"
    myDR(1) = "smith"
    myTB.Rows.Add(myDR)
    'king(blake)
    myDR = myTB.NewRow
    myDR(0) = "king"
    myDR(1) = "blake"
    myTB.Rows.Add(myDR)
    'blake(allen)
    myDR = myTB.NewRow
    myDR(0) = "blake"
    myDR(1) = "allen"
    myTB.Rows.Add(myDR)
    'blake(ward)
    myDR = myTB.NewRow
    myDR(0) = "blake"
    myDR(1) = "ward"
    myTB.Rows.Add(myDR)
    'king(clark)
    myDR = myTB.NewRow
    myDR(0) = "king"
    myDR(1) = "clark"
    myTB.Rows.Add(myDR)
    'clark(miller)
    myDR = myTB.NewRow
    myDR(0) = "clark"
    myDR(1) = "miller"
    myTB.Rows.Add(myDR)

    Return myDS
    End Function

    End Class更多精彩文章及讨论,请光临枫下论坛 rolia.net
    • 玩出点乐趣,再改进一下。
      本文发表在 rolia.net 枫下论坛Imports System.Linq

      Public Class Class4

      Public Sub AAA()
      Dim myDS As DataSet = createTestDS()

      Dim Xe As IEnumerable(Of XElement) = _
      From Item In ( _
      From E In myDS.Tables(0) _
      Where ( _
      From D In myDS.Tables(0) Where E("Parent") = D("Child") Select D _
      ).Count = 0 _
      Select E("Parent") Distinct) _
      Select Recursion(Item, myDS.Tables(0))

      Dim strHtml As String = ""
      For Each item In Xe
      strHtml += item.ToString
      Next
      MsgBox(strHtml)


      End Sub


      Private Function Recursion(ByVal Name As String, ByVal DT As DataTable) As XElement

      Dim myParentElement As XElement = _
      <ul>
      <li>
      <%= Name %>
      <%= From E In DT Where E("Parent") = Name Select Recursion(E("Child"), DT) %>
      </li>
      </ul>

      Return myParentElement

      End Function

      Private Function createTestDS() As DataSet
      Dim myDS As New DataSet
      Dim myTB As New DataTable
      Dim myCol As DataColumn
      myCol = New DataColumn("Parent")
      myTB.Columns.Add(myCol)
      myCol = New DataColumn("Child")
      myTB.Columns.Add(myCol)
      myDS.Tables.Add(myTB)

      Dim myDR As DataRow

      'king(jones)
      myDR = myTB.NewRow
      myDR(0) = "king"
      myDR(1) = "jones"
      myTB.Rows.Add(myDR)
      'jones(scott)
      myDR = myTB.NewRow
      myDR(0) = "jones"
      myDR(1) = "scott"
      myTB.Rows.Add(myDR)
      'scott(adams)
      myDR = myTB.NewRow
      myDR(0) = "scott"
      myDR(1) = "adams"
      myTB.Rows.Add(myDR)
      'jones(ford)
      myDR = myTB.NewRow
      myDR(0) = "jones"
      myDR(1) = "ford"
      myTB.Rows.Add(myDR)
      'ford(smith)
      myDR = myTB.NewRow
      myDR(0) = "ford"
      myDR(1) = "smith"
      myTB.Rows.Add(myDR)
      'king(blake)
      myDR = myTB.NewRow
      myDR(0) = "king"
      myDR(1) = "blake"
      myTB.Rows.Add(myDR)
      'blake(allen)
      myDR = myTB.NewRow
      myDR(0) = "blake"
      myDR(1) = "allen"
      myTB.Rows.Add(myDR)
      'blake(ward)
      myDR = myTB.NewRow
      myDR(0) = "blake"
      myDR(1) = "ward"
      myTB.Rows.Add(myDR)
      'king(clark)
      myDR = myTB.NewRow
      myDR(0) = "king"
      myDR(1) = "clark"
      myTB.Rows.Add(myDR)
      'clark(miller)
      myDR = myTB.NewRow
      myDR(0) = "clark"
      myDR(1) = "miller"
      myTB.Rows.Add(myDR)

      Return myDS
      End Function

      End Class更多精彩文章及讨论,请光临枫下论坛 rolia.net
    • 一点感想
      学了一个星期左右的LINQ,感觉基本100%LINQ提供的东西都可以用非LINQ来完成,LINQ象疯子一样地狂用delegate,使得许多变量不只是值的功能,还有行为在其中,这样用起来就很痛苦了,一个函数用了10边8边后,下次用的时候可能还是要查文档,代码变的很晦涩,而且里面的东西自己写根本不费事。
      • LINQ最经常用到的Delegate无非就是Action<>, Func<>,Predicate<>,只要记住这三个委托的用法就好了,你觉得很痛苦,我觉得很快乐,编程方便了很多呀
        • 可能是我没动力学习了,这Enumerable Members 里每个函数都有一大段说明,但每个自己实现起来简单又简单,实在没动力学。
      • 大量用Delegate并不是LINQ时代才有的,.Net 2.0就已经很多了,只不过2.0不支持 Lamda表达式,需要自己写很长的匿名委托函数
        比如List<T>.Find()函数,里面的定义是
        List<T>.FindAll(Predicate<T> match)

        这个Predicate委托就是在2.0时代开始大量应用的,举一个小例子看看2.0和3.5的区别
        找出所有字符串长度小于等于4的names

        用2.0来做
        List<string> names = new List<string>(new string[] { "tom", "grace", "wang", "zhang" });
        List<string> goodNames = names.FindAll(delegate(string s) { return s.Length <= 4; });

        用3.5来做
        List<string> names = new List<string>(new string[] { "tom", "grace", "wang", "zhang" });
        List<string> goodNames = names.FindAll(s => s.Length <= 4);

        有什么不同吗?唯一的不同就是用lamda表达式代替了讨厌的匿名委托

        当然,我们可以用.net 3.5的特殊语法更简洁的来写
        var goodNames = names.where(s=>s.Length <= 4).toList();

        不过核心思想和2.0时代的那段代码是一样的

        所以说,LINQ很多关键技术和思想在2.0时代就早已成熟并已经大量使用,微软只不过是更加完美的完善了一下而已
        • 您说的对。.NET太广了,要我就玩那些自己写比较费劲的东西,一个DadaGridView我玩了好几个月才玩熟巧,实在没时间玩自己写不费劲的东西。
          • 玩别人做的,那算什么! 要玩,就玩自己做的. 我自己的DadaGridView完全可以说是企业水平.
            • 牛哥牛,那把你的控件拿出来卖啊。BTW,市场上绝大部分第三方Grid控件的功能我都能在DataGridView上实现。
              • 一小例: re-usable portlet controlled by session variables, with configurable data source, and replaceable UI definition sheet. --- 迅弛猛牛开发系统提供支持 - 版权所有 2009
                • 牛哥牛,不过web的grid太简单,说白了就是一表格+template。
              • 这里面有个故事,
                组里有个活也是唯一的活做了5年,这从框架上肯定不能改了,后来来一个,技术不会仗着点关系,天天吵着第三方控件好,并做了点DEMO到处演示,差不多上升到你死我活的斗争,实在没办法,我只好把他DEMO里的花哨用纯.NET做出来来闭他的嘴。
                • 现在技术不是最重要的,主流语言基本都差不多,如果说区别,也逐步在缩小差距. 还停留在语言上是否大拿,那是意识上的落后. 现在讲究酷的设计: 界面酷! 它的背后就是: 流程酷! 算法酷! 想法酷! 如果还不够酷, 马上就能酷 !
                  我没说我酷, 还有很长的路.......
                  • 最酷是不干活光那钱。
                    • 老大,编个程序算算房价什么时候降吧,^_^
                      • 这可难那,不管我咋算,程序结果涨,实际降;程序结果降,实际升;把程序结果取反,实际跟着取反。
      • Linq的另外一大好处是利用Expression Tree打造自己的超级动态查询,或者是自己的Linq Provider,比如说,如果我愿意,我可以自己写一个Linq for Rola
        本文发表在 rolia.net 枫下论坛如果你看过Lambra Expression Tree的原理,就明白所有的Linq语句from ... where ... select 最后就要变成Lambra表达式,系统在把Lambra表达式变成Lambra Expression Tree,然后编译,然后运行。

        什么是Lambra Expression Tree呢?简单说一句,比如有如下这个表达式
        Expression<Func<int, int, int>> expression = (a, b) => a+ b;

        它的目的是,有两个int型的输入参数a,b,要求这个函数返回a+b的值,那么这个表达式
        (a, b) => a+ b
        可以用一棵树的形式来表达,分别是
        BinaryExpression(代表 a+b 这样一个动作,Root)
        |
        ParameterExpression(代表变量 a, Leaf) ParameterExpression(代表变量 b, Leaf)

        系统在把 (a, b) => a+ b 翻译成我写出的那个表达式tree之后,自己编译,然后运行,就得出a+b的答案

        这些动作在.net 3.5里可以用程序或者参数来控制,从而达到超级动态的目的,俺现在正在用这个特性写一个小项目,实现类似t-sql里面的 select ... from ... where ,目的是让操作人员自己输入一系列text文本的的“select ... where” 然后从一个特定的数据源中选出自己想要的数据

        不过,也有一部分人的观点是不要去碰Expression Tree,因为这是很复杂的一个过程。因为用Linq的目的是把复杂的事情简单化,现在用Expression Tree等于又要回到复杂的世界中去更多精彩文章及讨论,请光临枫下论坛 rolia.net
        • What’s the difference between your idea and LINQ Comprehension Syntax?
          • 从语法上看没什么区别,而且我也没精力完全实现Linq的那些语法,重点只是实现where后面的条件就是Func<T,bool> 的那部分
            本文发表在 rolia.net 枫下论坛我的问题是这样,或许你有更好地解决方案?我纯粹是被逼的,否则也不会走到用Expression Tree这一步

            据个例子来说明我的需求:

            有一个table,4个field,分别是
            name, age,address, postcode

            我要求在这4个fields中任意3个条件match,那么这个record就match,那么这个组合有多少呢?
            有4种可能性,如果用c#来写,我就要写4种if than, 或者写4种 Fun<T, bool> 委托,都是一回事。

            现在麻烦来了,我突然增加了一个field,变成了
            name, age,address, postcode, sex
            同样要求其中任意n种条件满足就返回相应的record,那么我又要修改程序写无数的if than来应付?

            显然这是不可能的任务,只能通过Expression Tree来做了

            我说的写一个自己的 selet ... where那纯粹是一个简单的text parser的工作,不是重点,重点在于如何把where后面的那些条件动态的变成IL语言,去某个数据storage去查询,比如我可以这么写

            select all where name='zhang' and age = '20'

            关键是把name='zhang' and age = '20'这个条件变成某种C#可以理解的东西来运行查询,而这个条件的变换是任意的,有无数种可能的组合,比如,下次我又可能把条件变成

            select all where name='zhang' and (address = 'toronto' or sex = 'male')

            目前,除了Expression Tree,我找不到更好的方法更多精彩文章及讨论,请光临枫下论坛 rolia.net
            • If you need to build multi-fields filter condition, you don’t have to use Expression Tree. Since it just builds a string condition, a sequence condition can achieve it.
              本文发表在 rolia.net 枫下论坛string filter(string name, int? age, string address, string postalCode, ref int count)
              {
              string condition = "";
              count = 0;
              if (name != null)
              {
              condition = string.Format(" Name='{0}' AND ", name.Replace("'", "''"));
              count++;
              }
              if (age != null)
              {
              condition += string.Format(" Age={0} AND ", age.Value);
              count++;
              }
              if (address != null)
              {
              condition += string.Format(" Address='{0}' AND ", address.Replace("'", "''"));
              count++;
              }
              if (postalCode != null)
              {
              condition += string.Format(" PostalCode='{0}' AND ", postalCode.Replace("'", "''"));
              count++;
              }
              return condition.Trim().TrimEnd("AND".ToCharArray());
              }

              'And' condition also can be achieved by Sequence Where

              IQueryable<TableName> q = DataContex.TableNames;
              int count = 0;
              if (name != null)
              {
              q = q.Where(t => t.Name.Equals(name));
              }
              if (age != null)
              {
              q = q.Where(t => t.age == age.Value);

              }
              if (address != null)
              {
              q = q.Where(t => t.address == address );

              }
              if (postalcode != null)
              {
              q = q.Where(t => t.postcode == postalcode);

              }更多精彩文章及讨论,请光临枫下论坛 rolia.net
              • 你这是for SQL数据库的,如果仅仅是for SQL数据库,当然可以用这种方法,数据库有parse SQL的天然能力。我的问题数据源不是SQL数据库,是一大堆文本文件,或者是XML,所以用表达式树
                • For text file, there is no problem to use SQL by oleDB provider. For XML, after being pulled into dataset, dataview's rowfilter is almost same as SQL where filter condition.
                  And as I mentioned, in IQueryable (or IEnumerable) .Where, AND condition can be expressed as chained Where, e.g.

                  q.Where(r => r.Name == name && r.Age == age && r.Address == address)
                  is same as
                  q.Where(r => r.Name == name).Where(r => r.Age == age).Where(r => r.Address == address)

                  Only OR condition should be built in more complicated way.
            • How does Bugzilla solve this problem? It allows user add as many matches as they want into the query and the performance is fast.