【问题标题】:add elements to int hashset from int array从 int 数组向 int hashset 添加元素
【发布时间】:2014-06-20 11:18:11
【问题描述】:

可以遍历数组,然后将元素一一添加到哈希集中。有什么方法可以在不迭代数组元素的情况下将整数从 int 数组添加到 int hashset??

 int[] pagesid;//int array
 var deletepages = new HashSet<int>();//hashset 
 pagesid= Array.ConvertAll(text.Split(','), s=>int.Parse(s));
 //values from pagesid should be added to hashset.

更新:

int[] pagesid;//int array
var deletepages = new HashSet<int>();//hashset 
foreach (XmlNode rule in pgmgmtrules)
{
  ruleresult=doc.ParseText(rule.InnerText, false);//parse rule
  if (ruleresult != "")
  { //if parsed rule result has value
    if (rule.Attributes["Action"].Value == "Delete")
    {
      var text=rule.Attributes["pageids"].Value;                                     
      pagesid= Array.ConvertAll(text.Split(','), s=>int.Parse(s));
     //add elements from pagesid array to hashset

    }
  }
}

【问题讨论】:

    标签: c# asp.net arrays hashset


    【解决方案1】:

    您可以使用以IEnumerable&lt;T&gt; 作为参数的重载构造函数HashSet Constructor (IEnumerable),而不是使用默认构造函数HashSet&lt;T&gt;()

    HashSet<int> evenNumbers = new HashSet<int>(text.Split(',').Select(int.Parse));
    

    HashSet Constructor (IEnumerable)

    初始化 HashSet 类的一个新实例,该实例使用 set 类型的默认相等比较器,包含复制的元素 从指定的集合,并有足够的容量 容纳复制的元素数量。

    编辑1如果你想从数组中过滤偶数,那么你可以使用Where

    var intArr = text.Split(',').Select(int.Parse);
    HashSet<int> evenNumbers = new HashSet<int>(intArr.Where(i=>i%2==0));
    

    编辑 2 基于 cmets。您可以使用 List&lt;int&gt; 代替 int 数组。在循环中继续在List 中添加int pageid,当循环 完成时,通过其构造函数HashSet Constructor (IEnumerable)HashSet 中添加List

    List<int> pagesid = new List<int>();//int array
    HashSet<int> deletepages = null;
    foreach (XmlNode rule in pgmgmtrules)
    {
      ruleresult=doc.ParseText(rule.InnerText, false);//parse rule
      if (ruleresult != "")
      { //if parsed rule result has value
        if (rule.Attributes["Action"].Value == "Delete")
        {
          var text=rule.Attributes["pageids"].Value;                                     
          pagesid.AddRange(text.Split(',').Select(int.Parse));
        }
      }
    }
    //add elements from pagesid array to hashset
    deletepages =  new HashSet<int>(pagesid);
    

    【讨论】:

    • 谢谢阿迪尔。但我不能每次都声明新的哈希集,因为我在循环中迭代,我希望他们继续添加到哈希集。
    • @MilindAnantwar 没有理由这样做。只需使用您需要的所有元素创建一个 IEnumerable,然后创建一个 HashSet。例如,如果您有多个文本,请对它们执行 Select
    • 如果您正在迭代数组并想要传递所有元素,那么您可以在构造函数中传递数组,但如果您想要选择性元素,则首先获取过滤后的数组并将其传递给 HashSet 构造函数。如果您以后想添加更多元素,则可以使用 Add 方法。
    • @Adil:我正在遍历 xml 节点。然后我得到整数数组中的元素。现在我需要在单词之后将数组元素添加到我需要的哈希集中。我已经更新了这个问题。再次感谢阿迪尔。
    • @MilindAnantwar 我建议使用 List 而不是 int 数组。请检查我的更新答案。
    【解决方案2】:

    从您的 int 数组中尝试这种简单的方法

     int[] pagesid;//int array
     var deletepages = new HashSet<int>();//hashset 
     pagesid = Array.ConvertAll("3,5,6,7".Split(','), s => int.Parse(s));
    //values from pagesid should be added to hashset.
     var hashset = new HashSet<int>(pagesid);
    

    【讨论】:

    • 构造函数接受任何 IEnumerable。没有理由将其转换为 List,您只需毫无理由地创建另一个临时对象
    【解决方案3】:

    HashSet 有一个constructor,它接受一个可枚举作为输入。你可以写一些简单的东西:

    var ints=text.Split(',')
                 .Select(s=>int.Parse(s));
    var set-new HashSet(ints);
    

    大多数内置泛型集合都接受 IEnumerable 作为源,因此您不必手动迭代源。

    更新

    从另一条评论看来,代码将在循环中运行,text 实际上是当前要处理的字符串。

    在这种情况下,更容易打破循环,创建所有文本的单个可枚举,然后进行转换,例如:

    var lines=new [] {"123,123","234,456"};
    
    var ints=from line in lines
             from s in line.Split(',')
             select int.Parse(s);
    var set=new HashSet(ints);
    

    var ints=lines.SelectMany(line=>line.Split(','))
                  .Select(s=>int.Parse(s));
    var set-new HashSet(ints);
    

    例如下面的 sn -p 解析文件中的所有数字:

    var lines=File.ReadAllLines(filePath);
    
    var ints=from line in lines
             from s in line.Split(',')
             select int.Parse(s);
    var set-new HashSet(ints);
    

    【讨论】:

      【解决方案4】:

      没有办法——即使 LINQ 也无济于事:

       sids = text.Split(',') // It is still array no matter what use
          .Select(str => int.Parse(s)); // This is where the loop over the array actually works
      
       deletePages = new HashSet<int>()(sids);
      

      因为String.Split 无论如何都会创建一个数组 - http://msdn.microsoft.com/en-us/library/b873y76a(v=vs.110).aspx

      但是,如果您创建自己的流式字符串拆分器:

      var deletePages = new HashSet<int>();//hashset 
      
       sids = text.MyStreamingStringSplit(',')
          .Select(str => int.Parse(s));
      
       var deletePages = new HashSet<int>(sids );//hashset
      

      您的流式字符串解析器可能如下所示:

      public static class StringExtensions
      {
          public static IEnumerable<String> StreamSplit(this String thisStr, char splitChar)
          {
              if (thisStr == null)
                  throw new ArgumentNullException();
      
              Int32 lastSplitterIndex = -1;
      
              for (Int32 i = 0; i < thisStr.Length; i++)
              { 
                  if (thisStr[i] == splitChar)
                  {
                       yield return thisStr.Substring(lastSplitterIndex + 1, i - lastSplitterIndex - 1);
                       lastSplitterIndex = i;
                  }
              }
      
              yield return thisStr.Substring(lastSplitterIndex + 1); 
          }
      }
      

      但性能只会有很小的提升(如果有的话)。所以我认为你应该坚持原来的解决方案 - 只需使用 HashSet&lt;T&gt;(IEnumerable&lt;T&gt;) 构造函数。

      【讨论】:

      • 我说没有遍历数组元素。
      • 实际上,集合的构造函数接受 IEnumerable 作为源是一种常见的 .NET 习惯用法。
      • 但是 String.Split 返回一个数组。
      • 数组是 IEnumerables
      • 但它们是数组 - 数组是创建的,而不是评估的。 IEnumerable 可以按需处理。如果是作者的意思。
      猜你喜欢
      • 2016-04-26
      • 2013-03-31
      • 1970-01-01
      • 2012-08-15
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多