序列化 HashSet与 LinQ

发布于 2024-09-24 02:36:51 字数 1482 浏览 3 评论 0原文

我想采用 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.Length-1); // remove final comma

是否有一种 LinQ 方法可以优雅且高效地完成此操作?

我能想到的唯一方法是首先将其转换为数组:

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

但是,然后我要做双重转换。是否有一些方便、高效、清晰的 LinQ 表达式?

答案 1(来自 marr 的想法)

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

    foreach (var i in items) 
        sb.AppendFormat("{0}{1}",i,joiner);

    if(sb.Length>0) 
        return sb.Remove(sb.Length - joiner.Length, joiner.Length).ToString();
    else
       return sb.ToString();
}

使用枚举器的答案 2(来自 Martin 的解决方案)

public static string JoinItems<T>(this IEnumerable<T> items, string delim) {
    var sb = new StringBuilder();
    var i = items.GetEnumerator();
    if (i.MoveNext()) {
        sb.Append(i.Current);
        while (i.MoveNext()) {
            sb.Append(delim);
            sb.Append(i.Current);
        }
    }
    return sb.ToString();
}

I'd like to take a HashSet<String> and elegantly convert it to a string. I can iterate like so:

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

Is there a LinQ way to do this elegantly and efficiently?

The only way I can think of doing this is by converting it to an array first:

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

But, then I'm doing a double conversion. Would there be some handy-dandy LinQ expression that's efficient and clear?

ANSWER 1 (from marr's idea)

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

    foreach (var i in items) 
        sb.AppendFormat("{0}{1}",i,joiner);

    if(sb.Length>0) 
        return sb.Remove(sb.Length - joiner.Length, joiner.Length).ToString();
    else
       return sb.ToString();
}

ANSWER 2 using an Enumerator (from Martin's solution)

public static string JoinItems<T>(this IEnumerable<T> items, string delim) {
    var sb = new StringBuilder();
    var i = items.GetEnumerator();
    if (i.MoveNext()) {
        sb.Append(i.Current);
        while (i.MoveNext()) {
            sb.Append(delim);
            sb.Append(i.Current);
        }
    }
    return sb.ToString();
}

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

我是有多爱你 2024-10-01 02:36:51

我采用了你的方法并将其修改为不需要删除最后一个逗号。我还将 AppendFormat 更改为 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(); 
} 

I took your method and modified it to not need to remove the last comma. I also changed the AppendFormat to just Append because it avoids all the work of parsing the format each time.

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(); 
} 
深爱成瘾 2024-10-01 02:36:51

这将在每次迭代时不需要额外的副本或检查来实现这一点:

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

This will do the trick without extra copies or checks on each iteration:

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();
}
清引 2024-10-01 02:36:51

我在 String.Join() 行中没有看到双重转换。我看到一个转换 ToArray(),这并不可怕,然后它执行 String.Join(),表现良好。

.Net 4 中有一个 String.Join() ,它需要无需转换即可工作的 IEnumerable。如果您使用的是较旧的框架版本,则可以为字符串编写自己的扩展方法,该方法采用分隔符作为“this”参数,然后加入 IEnumerable。确保使用 stringbuilder 来提高性能。

I don't see the double conversion in your String.Join() line. I see one conversion ToArray(), which is not terrible, and then it executes String.Join(), which performs well.

There is a String.Join() in .Net 4 that takes an IEnumerable that will work without the conversion. If you're using an older framework version, you can write your own extension method for string that takes a separator as the "this" parameter then joins an IEnumerable. Be sure and use stringbuilder for performance.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文