【问题标题】:How to get continuous characters in C#?如何在 C# 中获取连续字符?
【发布时间】:2011-05-03 19:17:33
【问题描述】:

我有一个

List<String> MyList=new List<string>();

我需要用n 值填充列表MyList

如果 n 的值为 2,则列表 MyList 将包含

"A","B"

如果是 10 则

"A","B","C"....."J"

如果是 30 则

"A"....."Z","AA","AB",AC","AD"

如果是 1000 则

"A",....."Z","AA","AB"......"AZ","BA","BB"......."BZ"........"YZ","AAA",AAB".....
and so on

我不知道该怎么做。

请帮助我使用任何方法使用LINQLAMBDA Expression 完成此操作

【问题讨论】:

  • 您需要 csv 吗?您可以使用 stringbuilder 并附加 n 个值,而不是使用 List。或者,您是否要将现有的字符串列表转换为 csv?
  • @Pavanred:我认为这里不需要任何 CSV - 只是一个字符串列表。
  • 为什么是“AB”...“AZ”和“ABC”...? “AA”和“AAA”有什么问题?
  • @Ken:这些不是 100% 重复的。如果将数字转换为字符串或创建连续的字符串序列,情况就不一样了。如果您看我的答案,它并不依赖于将数字转换为字符串。

标签: c# linq .net-3.5 lambda


【解决方案1】:

编辑 2

这可能是实现它的最简单方法。我测试了它,它工作正常。您可以生成无限数量的字符串。

public IEnumerable<string> GenerateStrings()
{
    foreach(string character in Alphabet())
    {
      yield return character;
    }

    foreach (string prefix in GenerateStrings())
    {
      foreach(string suffix in Alphabet())
      {
        yield return prefix + suffix;
      }
    }
}

public IEnumerable<string> Alphabet()
{
    for(int i = 0; i < 26; i++)
    {
      yield return ((char)('A' + i)).ToString();
    }
}

我之前写的东西:

您还可以编写一个小递归函数,该函数按某个索引返回任何字符串。这可能不是最佳性能明智的,因为有一些重复的划分,但它可能足够快以满足您的目的。

这很简短:

string GetString(int index)
{
  if (index < 26)
  {
    return ((char)('A' + index)).ToString();
  }
  return GetString(index / 26 - 1) + GetString(index % 26);
}

用法(也可以换成别的方法:

List<string> strings = Enumerable.Range(0, 1000)
  .Select(x => GetString(x))
  .ToList();

这是工作代码,刚刚为它写了一个测试。


编辑: 例如,GetString 的“全 linq 方式”应用:

public void IEnumerale<string> GenerateStrings()
{
  int index = 0;
  // generate "infinit" number of values ...
  while (true)
  {
     // ignoring index == int.MaxValue
     yield return GetString(index++);
  }
}

List<string> strings = GenerateStrings().Take(1000).ToList();

【讨论】:

  • 不错的方法,虽然 int i suffixCounter = 0; 无法编译,而且您不使用 isuffixCounter
【解决方案2】:

这类似于this question(但不足以将其标记为重复,而且无论如何搜索都是一个难题)。

使用任何有效的IEnumerable&lt;string&gt; 答案(或至少覆盖您需要的范围的任何答案),然后如果您需要创建包含一定数量元素的列表,只需使用:

List<string> list = GenerateSequence().Take(count).ToList();

【讨论】:

  • 这不是 imo 问题的真正答案。
  • 如果您认识到 Excel 所做的事情,搜索起来很容易——尝试搜索“excel column char”等。 :-)
  • @Stefan:在什么方面它不是问题的答案?从另一个问题中得到答案,添加额外的行,你就完成了。它到底有什么问题?
  • @Jon:问题是关于以某种方式生成字符串。您的回答更多是关于在您已经解决问题时使用 Take。
  • 斯特凡:我不同意。如果您关注 Jon 的链接,您将看到有关如何以某种方式生成字符串的问题的几个答案。唯一缺少的部分是 Jon 在此处添加的 .Take().ToList()
【解决方案3】:

不久前我在 SQL 中使用了something similar

翻译成 C#,这是一个从数字创建代码的函数:

public static string GetCode(int id) {
  string code, chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
  if (id <= chars.Length) {
    code = chars.Substring(id - 1, 1);
  } else {
    id--;
    int value = chars.Length, adder = 0;
    while (id >= value * (chars.Length + 1) + adder) {
      adder += value;
      value *= chars.Length;
    }
    code = chars.Substring((id - adder) / value - 1, 1);
    id = ((id - adder) % value);
    while (value > 1) {
      value /= chars.Length;
      code += chars.Substring(id / value, 1);
      id = id % value;
    }
  }
  return code;
}

然后您只需获取 1 及以上的数字,然后转换为代码:

var codes = Enumerable.Range(1, 1000).Select(n => GetCode(n));

目前函数的限制是“ZZZZZZ”或321272406。(之后你得到一个除以零。)

请注意,此函数使用所有组合并返回“A”..“Z”、“AA”..“ZZ”、“AAA”...“ZZZ”,而不是从“AB”和“ABC”开始.

【讨论】:

    【解决方案4】:

    这段代码运行良好,但我不确定它是否“足够 LINQ”。

    char[] validChars = Enumerable.Range(0, 26).Select(i => (char)('A' + i)).ToArray();
    List<string> result = new List<string>();
    List<string> generator = validChars.Select(ch => ch.ToString()).ToList();
    
    int n = 1000;
    
    while (result.Count < n)
    {
        result.AddRange(generator);
        generator = generator.Take((n - result.Count) / validChars.Length + 1)
                             .SelectMany(s => validChars.Select(ch => s + ch))
                             .ToList();
    }
    
    var output = result.Take(n);
    

    【讨论】:

    • 从“AZ”直接跳到“ABC”,从“ABZ”跳到“ABCD”。
    • @Danny Chen:现在它可以工作了,但效率不高......它创建了 50 万个字符串来获得前一千个......
    • @Guffa:我不得不同意你的观点:(这个问题是SelectMany带来的,它会批量生成连续的字符。但我认为如果n不是那么大,这是一个好主意,因为代码更具可读性和易于管理。
    • @Guffa:我在SelectMany 之前添加了一个Take 方法,现在它更有效了。感谢您的建议。
    • @Danny Chen:现在您总是创建一个在退出循环之前从未使用过的集合。从generator = new List&lt;string&gt; { "" } 开始并在循环中首先填充生成器怎么样。 :)
    【解决方案5】:

    试试下面 .. 我正在使用 Cross JoinUnion 来构建源,然后使用 Take 扩展方法过滤记录强>

    char[] charArray = "ABCDEFGHIJKLMNOPQRSTUVWXYZ".ToCharArray();
    
    List<String> MyList = new List<string>();
    int n = 1000;
    
                          (from value1 in charArray
                           select new
                           {
                               newString = value1.ToString()
                           })
                       .Union
                       (
                           (from value1 in charArray
                            from value2 in charArray
    
                            select new
                            {
                                newString = string.Concat(value1, value2)
                            })
                        )
                        .Union
                        (
                            (from value1 in charArray
                             from value2 in charArray
                             from value3 in charArray
    
                             select new
                             {
                                 newString = string.Concat(value1, value2, value3)
                             })
                         )
                         .Take(n)
                         .ToList()                         
                         .ForEach(i => MyList.Add(i.newString));
    

    希望这能让您对使用 Linq、Lambda 和 Extension 方法的组合有所了解。

    【讨论】:

      【解决方案6】:

      @DannyChen 就是这样。您的代码稍作改动..

      char[] validChars = Enumerable.Range(0, 26).Select(i => (char)('A' + i)).ToArray();
      
      int n = 30;
      int pointer = 0;
      int pointerSec = 0;
      int Deg = 0;
      string prefix = string.Empty;
      string prefixMore = string.Empty;
      List<string> result = new List<string>();
      
      while (n > 0)
      {
          result.AddRange(validChars.Skip(pointer).Select(ch => prefix + ch).Take(n));
          if (pointer == 26)
          { 
              pointer = -1;
              Deg += 1;
              prefixMore = "" + validChars[pointerSec];
              pointerSec++;
              n++;
          }
          else
          {
              if (Deg == 0)
              {
                  prefix = "" + validChars[pointer];
              }
              else
              {
                  prefix = prefixMore + validChars[pointer];
              }
          }
          n--;
          pointer++;
      }
      

      100% 正确。

      【讨论】:

      • @Pramodh...是你想要的...!
      猜你喜欢
      • 2016-02-16
      • 1970-01-01
      • 2014-04-23
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-11-22
      相关资源
      最近更新 更多