【问题标题】:How to get all values in a given alphanumeric range [closed]如何获取给定字母数字范围内的所有值
【发布时间】:2020-09-09 08:32:27
【问题描述】:

我有一个字符串 x = "AB001-AB050, AB055, AB060-AB099"。

我正在寻找一种解决方案来获取此范围内的所有值。

输出应包含AB001AB050 之间的所有值,然后是AB055,然后是AB060AB099 之间的所有值。

附加细节:前 2 个字符只是字母。最后 3 个字符只是数字。

示例:给定 AB008 - AB012, AB020 预期 o/p : AB008, AB009, AB010,AB011, AB012,AB020

【问题讨论】:

  • 你的输入数据是什么?
  • 标识符的格式是否始终为<one-or-more-letters><one-or-more-digits>,并且您希望所有标识符具有相同的字母,但数字在小数和大数之间变化?
  • 在上下范围内是否总是相同的字母?或者你能有这个吗? AB001-AC050 ?
  • 将 AB001 视为基数为 36 的数字。然后从 AB001 到 AB002 的增量可以通过转换为基数 10 来完成。stackoverflow.com/questions/923771/…。我假设您将能够拆分 ,- 以获得范围限制。如果不是那 3 个问题。
  • 这是一个相当幼稚的例子:dotnetfiddle.net/hJZH1W

标签: c# string range alphanumeric


【解决方案1】:

你在寻找这样的东西吗?

var prefix = "AB";
var x = "AB001-AB050, AB055, AB060-AB099";

var lean_x = x.Replace(prefix, "");

var ranges = lean_x.Split(',').Select(x =>
{
    var  interval = x.Split('-').Select(x => Convert.ToInt32(x)).ToArray();
    if (interval.Count() > 1)
        return Enumerable.Range(interval[0], interval[1] - interval[0] + 1);
        
    return Enumerable.Range(interval[0], 1);
}).SelectMany(p => p, (p,q) =>String.Format("{0}{1:000}", prefix, q));


ranges.Dump();

【讨论】:

  • 很好,如果前缀必须是递增的。删除Replace。用FromBase26To10 包裹每个interval[]。还有SelectManyFromBase10ToBase26
  • 好提示。 @SagarChopra 剩下的就是你的了。努力吧:)
  • 我已经提交了一个答案,因为我发现只用复制过去来解决这个变体很有趣。我可以使用您的解决方案进行解析吗?我可以很容易地做简单的循环。答案如下。
  • @Lasse V. Karlsen。格式将始终为 [A-Z][A-Z][0-9][0-9][0-9]。
  • @DervişKayımbaşıoğlu 这正是我想要实现的,但我想增加前缀。这真的很有帮助。谢谢。
【解决方案2】:

如果您不需要增加这封信,这里也是基于链接和现有答案的解决方案。

Base 26 -> 10 转换:
基于Quickest way to convert a base 10 number to any base in .NET?

private static readonly char[] BaseChars =
 "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ".ToCharArray();
private static readonly Dictionary<char, int> CharValues = BaseChars
           .Select((c, i) => new { Char = c, Index = i })
           .ToDictionary(c => c.Char, c => c.Index);

public static string LongToBase(long value)
{
    long targetBase = BaseChars.Length;
    // Determine exact number of characters to use.
    char[] buffer = new char[Math.Max(
               (int)Math.Ceiling(Math.Log(value + 1, targetBase)), 1)];

    var i = buffer.Length;
    do
    {
        buffer[--i] = BaseChars[value % targetBase];
        value = value / targetBase;
    }
    while (value > 0);

    return new string(buffer, i, buffer.Length - i);
}

public static long BaseToLong(string number)
{
    char[] chrs = number.ToCharArray();
    int m = chrs.Length - 1;
    int n = BaseChars.Length, x;
    long result = 0;
    for (int i = 0; i < chrs.Length; i++)
    {
        x = CharValues[chrs[i]];
        result += x * (long)Math.Pow(n, m--);
    }
    return result;
}

解析输入:
基于Dervis answer

var ranges = valuePart.Split(',')
                      .Select(x => {
                          var range = x.Split('-')
                                        .Select(x=> x.Trim()) // only thing I typed
                                        .ToList();

                          if (range.Count() > 1)
                              return RangeLong(BaseToLong(range[0]), BaseToLong(range[1]) - BaseToLong(range[0]) + 1);

                          return RangeLong(BaseToLong(range[0]), 1);
                      });

var result = ranges.SelectMany(x => x.Select(y=> LongToBase(y))).ToList();
        

Enumerable range for long 的简单实现: 基于https://referencesource.microsoft.com/#System.Core/System/Linq/Enumerable.cs,1271

static IEnumerable<long> RangeLong(long start, long count)
{
    for (long i = 0; i < count; i++) yield return start + i;
}
    

Live demo.

此代码仅使用来自与此问题相关的代码和资源的 copypast 构建,仅输入了 .Select(x=&gt; x.Trim())

【讨论】:

    猜你喜欢
    • 2015-07-28
    • 1970-01-01
    • 1970-01-01
    • 2017-03-23
    • 1970-01-01
    • 2013-02-15
    • 1970-01-01
    • 2017-12-02
    相关资源
    最近更新 更多