【问题标题】:order datatable by relevance using linq by column values which are comma sperated使用 linq 按逗号分隔的列值按相关性排序数据表
【发布时间】:2010-08-31 16:12:22
【问题描述】:

我有一个数据表,其中包含一个名为标签的列,标签可以具有诸如

之类的值
row[0] = Tag1
row[1] = Tag1, Tag2
row[2] = Tag2, Tag3
row[3] = Tag1, Tag2, Tag3
row[4] = Tag4, Tag6

并用逗号分隔

等等。

我有当前文档的标签值,并运行了一个查询来选择所有其他在该行中具有任一标签的文档。例如,假设当前文档标签是 (Tag1, Tag2, Tag3)

所以从上面的示例行中,除了 row[4] 之外,上面的所有行都返回

这是我丢失的一点,我现在想根据与当前文档匹配的标签数量对数据表进行排序。所以对于我到目前为止所讨论的示例,它们应该被订购

row[3] = Tag1, Tag2, Tag3
row[1] = Tag1, Tag2
row[2] = Tag2, Tag3
row[0] = Tag1

以前没有使用过 linq,但被告知它可以做到这一点。

目前为止

var query = from c in dt.AsEnumerable()
                    orderby c.Field<string>("Tags").CompareTo(dr["Tags"]) ascending
                    select c;

【问题讨论】:

    标签: c# asp.net database linq


    【解决方案1】:

    使用相交方法。这是一个示例

    //test data
    DataTable table = new DataTable();
            var column = table.Columns.Add("Tags", typeof(string));
            table.Rows.Add("Tag1");
            table.Rows.Add("Tag1,Tag2");
            table.Rows.Add("Tag2,Tag3");
            table.Rows.Add("Tag1,Tag2,Tag3");
            table.Rows.Add("Tag4,Tag6");
            string[] currentTags = new string[] { "Tag1", "Tag2", "Tag3" };
    
    //actual code
            var a = from row in table.AsEnumerable()
                    let cData = (row["Tags"] as string).Split(new char[] { ',' }).Intersect(currentTags)
                    orderby cData.Count() descending
                    select cData;
    

    【讨论】:

    • 也可以,但 kbrimington 是最快的。哪一个对性能更好还是与 linq 无关?
    • 不要认为它在性能方面有很大的不同。我正在使用一个可用的内置 API(我总是喜欢它),并且 kbrimington 使用了 lamda 表达式来实现相交。 P.S - 不会阻止你给我一个赞成票。我只是给了你另一种方法
    • 我会,但我还没有 15 声望。从来没听说过lamda的表情会查一下。你能看看下面的,看看你的想法吗
    【解决方案2】:

    我认为这样的事情符合要求。试试看:

    // Here, I construct a simple table for demonstration
    var table = new DataTable();
    var column = table.Columns.Add("Tags", typeof(string));
    table.Rows.Add("Tag1");
    table.Rows.Add("Tag1, Tag2");
    table.Rows.Add("Tag2, Tag3");
    table.Rows.Add("Tag1, Tag2, Tag3");
    table.Rows.Add("Tag4, Tag6");
    
    // The separator is convenient for using the string.Split override
    // that strips empty results
    var separator = new[] { ",", " " };
    
    // For the demo, we'll sort by number of tags matching the third row
    var current = table.Rows[2];
    
    // This splits the string into an array for convenient processing later
    var currenttags = current.Field<string>("Tags")
                             .Split(separator, StringSplitOptions.RemoveEmptyEntries);
    
    // The query splits out each tags field into an array convenient for processing,
    // counts the number of tags contained in the currenttags array,
    // sorts, and then selects the entire row.
    var query = from row in table.AsEnumerable()
                let tags = row.Field<string>("Tags")
                              .Split(separator, StringSplitOptions.RemoveEmptyEntries)
                let count = tags.Count(t => currenttags.Contains(t))
                orderby count descending
                select row;
    

    【讨论】:

      【解决方案3】:
              string[] Tags = dr["Tags"].ToString().Split(new char[] { ',' });
              string SqlClause = "";
      
              for (int i = 0; i < Tags.Length; i++)
              {
                  if (i != Tags.Length - 1)
                  {
                      SqlClause += "Tags LIKE '%" + Tags[i] + "%' OR ";
                  }
                  else
                  {
                      SqlClause += "Tags LIKE '%" + Tags[i] + "%'";
                  }
              }
      
              DataTable dt = ArticleCollection(SqlClause);
      
              var seperator = new[] { ",", " " };
              var current = dr["Tags"].ToString();
              var currenttags = dr.Field<string>("Tags").Split(seperator, StringSplitOptions.RemoveEmptyEntries);
      
              DataTable query = (from row in dt.AsEnumerable()
                          let tags = row.Field<string>("Tags").Split(seperator, StringSplitOptions.RemoveEmptyEntries)
                          let count = tags.Count(t => currenttags.Contains(t))
                          orderby count descending
                          select row).CopyToDataTable();
      
              for (int i = 0; i < query.Rows.Count; i++)
              {
                  if (query.Rows[i]["Title"].ToString() == dr["Title"].ToString())
                  {
                      query.Rows[i].Delete();
                  }
              }
      
              TagsRepeater.DataSource = query;
              TagsRepeater.DataBind();
      
          }
      }
      
      DataTable ArticleCollection(string whereClause)
      {
      
          DataSet ds = TreeHelper.SelectNodes("/%", false, "CriticalCare.Conclusion;CriticalCare.Literature;CriticalCare.Theory", whereClause, " ", -1, true);
          DataTable dt = new DataTable();
      
          if (!DataHelper.DataSourceIsEmpty(ds))
          {            
              for (int i = 0; i < ds.Tables.Count; i++)
              {
                  dt.Merge(ds.Tables[i]);
              }
              return dt;
          }
          return null;
      }
      

      }

      我还想做的是,如果不止一篇文章匹配相同数量的标签,则按照与站点树中当前文档相关的顺序对它们进行排序。我会用哪一点 linq 来做呢?在同一个查询中很容易做到这一点吗?是否可以向数据表添加计数列?

      【讨论】:

      • 你能举例说明吗,也不要发布问题编辑作为答案
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-10-26
      • 1970-01-01
      相关资源
      最近更新 更多