从整数数组向整数哈希集合中添加元素

3

可以遍历数组,然后逐个向哈希集合中添加元素。但是有没有一种方法可以将整数数组中的整数添加到整数哈希集合中,而不必遍历数组元素?

 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

    }
  }
}
4个回答

3
您可以使用重载构造函数HashSet Constructor (IEnumerable),它以IEnumerable<T>作为参数,而不是使用默认构造函数HashSet<T>()
HashSet<int> evenNumbers = new HashSet<int>(text.Split(',').Select(int.Parse));

HashSet构造函数(IEnumerable)

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

编辑1 如果您想从数组中过滤偶数,则可以使用Where。

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

编辑 2 基于评论。您可以使用List<int>代替int数组。在循环中持续将int页面ID添加到List中,当循环完成时,通过其构造函数HashSet Constructor(IEnumerable)List添加到HashSet中。

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);

谢谢Adil。但是我不能每次都声明一个新的HashSet,因为我正在循环中进行迭代,并且我希望它们继续添加到HashSet中。 - Milind Anantwar
@MilindAnantwar 没有理由这样做。只需创建一个包含所需元素的IEnumerable,然后创建一个单独的HashSet。例如,如果你有多个文本,请对它们进行Select操作。 - Panagiotis Kanavos
如果你正在遍历数组并且想要传递所有元素,那么你可以在构造函数中传递数组。但是,如果你只想选择性地传递元素,则首先获取筛选后的数组,并将其传递给HashSet的构造函数。如果以后想要添加更多元素,则可以使用Add方法。 - Adil
@Adil:我正在遍历XML节点。然后,我将元素存储在整数数组中。现在,我需要将数组元素添加到HashSet中,以便稍后使用。我已经更新了问题。再次感谢,Adil。 - Milind Anantwar
@MilindAnantwar 我建议使用List<int>而不是int数组。请查看我的更新答案。 - Adil

1

尝试使用你的整数数组来实现这种简单的方法

 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<T>。没有理由将其转换为 List<T>,你只是无谓地创建了另一个临时对象。 - Panagiotis Kanavos

0

没有办法 - 即使是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<T>(IEnumerable<T>) 构造函数即可。


我说过不要遍历数组元素。 - Milind Anantwar
实际上,这是一种常见的.NET习语,用于集合的构造函数接受一个IEnumerable作为源。 - Panagiotis Kanavos
但是String.Split返回一个数组。 - Eugene Podskal
数组是可枚举的。 - Panagiotis Kanavos
但它们是数组 - 数组是被创建的,而不是被评估的。IEnumerable 可以按需处理。如果这是作者的意思的话。 - Eugene Podskal

0

HashSet有一个构造函数,它接受一个可枚举对象作为输入。你可以简单地写成:

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);

例如,以下代码片段解析文件中的所有数字:
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);

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接