Linq 序列化哈希集<;字符串>;与林克

Linq 序列化哈希集<;字符串>;与林克,linq,string,join,hashset,Linq,String,Join,Hashset,我想要一个哈希集,并优雅地将其转换为字符串。我可以这样迭代: HashSet<String> words = new HashSet<string>() { "alpha", "beta", "delta" }; string joined = ""; foreach (var w in words) joined += w + ","; if(joined.Length > 0) joined = joined.SubString(0,joined.

我想要一个
哈希集
,并优雅地将其转换为字符串。我可以这样迭代:

HashSet<String> words = new HashSet<string>() { "alpha", "beta", "delta" };

string joined = "";
foreach (var w in words) 
  joined += w + ",";

if(joined.Length > 0)
  joined = joined.SubString(0,joined.Length-1); // remove final comma
但是,我在做双重转换。会不会有一些方便、高效、清晰的dandy LinQ表达

答案1(来自marr的想法)

公共静态字符串JoinItems(此IEnumerable items,字符串joiner){
StringBuilder sb=新的StringBuilder(“”);
foreach(项目中的var i)
sb.AppendFormat(“{0}{1}”,i,joiner);
如果(某人长度>0)
返回某人删除(sb.Length-joiner.Length,joiner.Length).ToString();
其他的
使某人返回字符串();
}
答案2使用枚举器(来自Martin的解决方案)

公共静态字符串JoinItems(此IEnumerable items,字符串delim){
var sb=新的StringBuilder();
var i=items.GetEnumerator();
if(i.MoveNext()){
某人追加(即当前);
while(i.MoveNext()){
某人追加(删除);
某人追加(即当前);
}
}
使某人返回字符串();
}

我在String.Join()行中没有看到双重转换。我看到一个到array()的转换,这并不可怕,然后它执行String.Join(),这执行得很好


在.NET4中有一个函数,它接受一个IEnumerable,该函数在不进行转换的情况下工作。如果您使用的是较旧的框架版本,则可以为字符串编写自己的扩展方法,该方法将分隔符作为“this”参数,然后加入IEnumerable。请确保使用stringbuilder提高性能。

我在String.Join()行中没有看到双重转换。我看到一个到array()的转换,这并不可怕,然后它执行String.Join(),这执行得很好


在.NET4中有一个函数,它接受一个IEnumerable,该函数在不进行转换的情况下工作。如果您使用的是较旧的框架版本,则可以为字符串编写自己的扩展方法,该方法将分隔符作为“this”参数,然后加入IEnumerable。确保并使用stringbuilder提高性能。

这将在每次迭代中不需要额外副本或检查的情况下实现此功能:

String JoinItems<T>(IEnumerable<T> items) {
  var stringBuilder = new StringBuilder();
  var i = items.GetEnumerator();
  if (i.MoveNext()) {
    stringBuilder.Append(i.Current);
    while (i.MoveNext()) {
      stringBuilder.Append(", ");
      stringBuilder.Append(i.Current);
    }
  }
  return stringBuilder.ToString();
}
字符串连接项(IEnumerable项){
var stringBuilder=新的stringBuilder();
var i=items.GetEnumerator();
if(i.MoveNext()){
stringBuilder.Append(i.Current);
while(i.MoveNext()){
stringBuilder.Append(“,”);
stringBuilder.Append(i.Current);
}
}
返回stringBuilder.ToString();
}

这将在每次迭代中不需要额外拷贝或检查的情况下完成该技巧:

String JoinItems<T>(IEnumerable<T> items) {
  var stringBuilder = new StringBuilder();
  var i = items.GetEnumerator();
  if (i.MoveNext()) {
    stringBuilder.Append(i.Current);
    while (i.MoveNext()) {
      stringBuilder.Append(", ");
      stringBuilder.Append(i.Current);
    }
  }
  return stringBuilder.ToString();
}
字符串连接项(IEnumerable项){
var stringBuilder=新的stringBuilder();
var i=items.GetEnumerator();
if(i.MoveNext()){
stringBuilder.Append(i.Current);
while(i.MoveNext()){
stringBuilder.Append(“,”);
stringBuilder.Append(i.Current);
}
}
返回stringBuilder.ToString();
}

我采用了您的方法,并将其修改为不需要删除最后一个逗号。我还将
AppendFormat
更改为just
Append
,因为它避免了每次解析格式的所有工作

public static string JoinItems(this IEnumerable<string> items, string joiner)
{
    StringBuilder sb = new StringBuilder(); 
    string delim = "";

    foreach (var i in items)
    {
        sb.Append(delim);
        sb.Append(i);
        delim = joiner;
    }

    return sb.ToString(); 
} 
公共静态字符串JoinItems(此IEnumerable items,字符串joiner)
{
StringBuilder sb=新的StringBuilder();
字符串delim=“”;
foreach(项目中的var i)
{
某人追加(删除);
某人(i);
delim=细木工;
}
使某人返回字符串();
} 

我采用了您的方法,并将其修改为不需要删除最后一个逗号。我还将
AppendFormat
更改为just
Append
,因为它避免了每次解析格式的所有工作

public static string JoinItems(this IEnumerable<string> items, string joiner)
{
    StringBuilder sb = new StringBuilder(); 
    string delim = "";

    foreach (var i in items)
    {
        sb.Append(delim);
        sb.Append(i);
        delim = joiner;
    }

    return sb.ToString(); 
} 
公共静态字符串JoinItems(此IEnumerable items,字符串joiner)
{
StringBuilder sb=新的StringBuilder();
字符串delim=“”;
foreach(项目中的var i)
{
某人追加(删除);
某人(i);
delim=细木工;
}
使某人返回字符串();
} 


也许您不知道string.Join的过载情况,它需要一个可枚举的?(包括HashSet)@Kirk-只有4.0有这个重载。3.5没有。也许您没有意识到string.Join的重载,它需要一个可枚举的?(包括HashSet)@Kirk-只有4.0有这个重载。3.5没有。我不确定我会用“双重转换”来形容它,但它是“两次转换”。问题是,尽管。。。是否有一个LinQ版本是一次性的。。。还是说是幕后的两个关卡?注意:我意识到ToArray()当然是一个LinQ扩展方法……它不是IEnumerable重载的两次传递,string.Join使用的字符串数组的唯一方面是对其进行枚举。就像我说的,写一个扩展方法,它接受一个可枚举的,只是不要像你所展示的那样,使用一个stringbuilder。对不起,我太笨了。我正在看我制作的第二个示例,想知道如何实现stringbuilder,但是,我现在看到了。。。你的意思是拿着原件,用一个StringBuilder。明白了!我不确定我会用“双重转换”来形容它,但它是“两次转换”。问题是,尽管。。。是否有一个LinQ版本是一次性的。。。还是说是幕后的两个关卡?注意:我意识到ToArray()当然是一个LinQ扩展方法……它不是IEnumerable重载的两次传递,string.Join使用的字符串数组的唯一方面是对其进行枚举。就像我说的,写一个扩展方法,它接受一个可枚举的,只是不要像你所展示的那样,使用一个stringbuilder。对不起,我太笨了。我正在看我制作的第二个示例,想知道如何实现stringbuilder,但是,我现在看到了。。。你的意思是拿着原件,用一个StringBuilder。明白了!这很好,我的库版本有签名连接(这个字符串分隔符,IEnumerable items),因为它模仿python语法。给每个人自己的。非常好!这是一个很棒的技巧,非常好。请注意,对于StringBuilder还是string.Join对于大型集合来说速度更快,也存在争议。。。即使某人很快,它也可能需要成长
public static string JoinItems(this IEnumerable<string> items, string joiner)
{
    StringBuilder sb = new StringBuilder(); 
    string delim = "";

    foreach (var i in items)
    {
        sb.Append(delim);
        sb.Append(i);
        delim = joiner;
    }

    return sb.ToString(); 
}