Получить диапазон из двух целых чисел

1
string num = db.SelectNums(id);
string[] numArr = num.Split('-').ToArray();

string num содержит пример "48030-48039";

string[] numArr будет содержать (48030, 48039).

Теперь у меня есть два элемента: высокий и низкий. Теперь мне нужно получить ВСЕ числа от 48030 до 48039. Проблема в том, что она должна быть строкой, так как теперь будут номера телефонов с ведущими нулями.

Вот почему я не могу использовать Enumerable.Range().ToArray() для этого.

Какие-либо предложения? Ожидаемый результат должен быть 48030, 48031, 48032,..., 48039

Теги:

8 ответов

1
Лучший ответ

Это должно работать с вашим основным нулевым требованием:

string num = db.SelectNums(id);
string[] split = num.Split('-');

long start = long.Parse(split[0]);
long end = long.Parse(split[1]);
bool includeLeadingZero = split[0].StartsWith("0");

List<string> results = new List<string>();

for(int i = start; i <= end; i++)
{
    string result = includeLeadingZero ? "0" : "";
    result += i.ToString();
    results.Add(result);
}

string[] arrayResults = results.ToArray();

Несколько замечаний:

  • Предполагается, что ваш вход будет состоять из 2 действительных целых чисел, разделенных одним дефисом
  • Я даю вам результат строкового массива, лично я предпочел бы работать со List<int> в конце
  • Если первое число содержит единственный начальный ноль, то все результаты будут содержать один начальный ноль
  • Он использует long для обслуживания более длинных номеров, остерегайтесь того, что максимальное число, которое будет анализироваться, равно 9,223,372,036,854,775,807, вы можете удвоить это значение (не длина), используя ulong
  • 0
    Я попробовал это, и «я понял, что значение было слишком большим или слишком маленьким для Int32». split [0] содержит "4618155500". Помните, что 48030 это просто пример. Числа будут сильно различаться.
  • 0
    @ user3218338: Сколько ведущих нулей ты хочешь тогда? В вашем примере было всего 5 цифр. РЕДАКТИРОВАТЬ: Тогда в этом случае вы можете рассмотреть возможность использования long , но теперь мне интересно, слишком ли велики диапазоны в этом случае, чтобы их можно было использовать; мы можем использовать отсроченное исполнение здесь.
Показать ещё 7 комментариев
0

Полное решение, вдохновленное ответом @Dan-o:

Входы:

Start:  48030
End:    48039
Digits:     6

Ожидаемый вывод строки:

048030, 048031, 048032, 048033, 048034, 048035, 048036, 048037, 048038, 048039

Программа:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

public class Program
{
    public static void Main()
    {
        int first  = 48030;
        int last   = 48039;
        int digits = 6;

        Console.WriteLine(CreateRange(first, last, digits));
    }

    public static string CreateRange(int first, int last, int numDigits)
    {
        string separator = ", ";

        var sb = new StringBuilder();
        sb.Append(first.ToString().PadLeft(numDigits, '0'));

        foreach (int num in Enumerable.Range(first + 1, last - first))
        {
            sb.Append(separator + num.ToString().PadLeft(numDigits, '0'));
        }

        return sb.ToString();
    }
}
0

В комментариях были затронуты три существенных вопроса:

  1. Номера телефонов имеют достаточно цифр, чтобы превышать Int32.MaxValue поэтому преобразование в int не является жизнеспособным.

  2. Номера телефонов могут иметь ведущие нули (предположительно для некоторых международных звонков?)

  3. Возможный диапазон чисел может теоретически превышать максимальный размер массива (который может иметь проблемы с памятью, и я думаю, что он не может быть представлен как string)

Таким образом, вам может потребоваться использовать long вместо int, и я бы предложил использовать отложенное выполнение, если это необходимо для очень больших диапазонов.

public static IEnumerable<string> EnumeratePhoneNumbers(string fromAndTo)
{
    var split = fromAndTo.Split('-');

    return EnumeratePhoneNumbers(split[0], split[1]);
}

public static IEnumerable<string> EnumeratePhoneNumbers(string fromString, string toString)
{
    long from = long.Parse(fromString);
    long to = long.Parse(toString);

    int totalNumberLength = fromString.Length;

    for (long phoneNumber = from; phoneNumber <= to; phoneNumber++)
    {
        yield return phoneNumber.ToString().PadLeft(totalNumberLength, '0');
    }
}

Это предполагает, что заполненные нули уже включены в нижнюю границу текста fromString. Он будет перебирать и выдавать номера по мере необходимости. Это может быть полезно, если вы производите много номеров и не нуждаетесь в их заполнении, или вам нужны только первые 10 или 100. Например:

var first100Numbers = 
    EnumeratePhoneNumbers("0018155500-7018155510")
    .Take(100)
    .ToArray();

Обычно этот диапазон выдавал бы 7 миллиардов результатов, которые не могут быть сохранены в массиве, и могут возникать проблемы с памятью (я даже не уверен, может ли он быть сохранен в строке); используя отложенное выполнение, вы создаете только 100 необходимых.

Если у вас есть небольшой диапазон, вы можете объединить свои результаты в строку, как вам было угодно:

string numberRanges = String.Join(", ", EnumeratePhoneNumbers("0018155500-0018155510"));

И, естественно, вы можете поместить это создание массива в свой собственный вспомогательный метод:

public static string GetPhoneNumbersListing(string fromAndTo)
{
    return String.Join(", ", EnumeratePhoneNumbers("0018155500-0018155510"));
}

Таким образом, ваше использование будет:

string numberRanges = GetPhoneNumbersListing("0018155500-0018155510");
0

Это один из способов сделать это:

    public static string[] RangeTest()
    {
        Boolean leadingZero = false;
        string num = "048030-48039"; //db.SelectNums(id);
        if (num.StartsWith("0"))
            leadingZero = true;

        int min = int.Parse(num.Split('-').Min());
        int count = int.Parse(num.Split('-').Max()) - min;
        if (leadingZero)
            return Enumerable.Range(min, count).Select(x => "0" + x.ToString()).ToArray();
        else
            return Enumerable.Range(min, count).Select(x => "" + x.ToString()).ToArray(); ;
    }
0

Вы можете использовать string.Format для обеспечения того, чтобы числа форматировались с ведущими нулями. Это заставит метод работать с произвольным числом начальных нулей.

private static string CreateRange(string num)
{
    var tokens = num.Split('-').Select(s => s.Trim()).ToArray();

    // use UInt64 to allow huge numbers
    var start = UInt64.Parse(tokens[0]);
    var end = UInt64.Parse(tokens[1]);

    // if your start number is '000123', this will create
    // a format string with 6 zeros ('000000')
    var format = new string('0', tokens[0].Length);

    // use StringBuilder to make GC happy.
    // (if only there was a Enumerable.Range<ulong> overload...)
    var sb = new StringBuilder();
    for (var i = start; i <= end; i++)
    {
        // format ensures that your numbers are padded properly
        sb.Append(i.ToString(format));
        sb.Append(", ");
    }

    // trim trailing comma after the last element
    if (sb.Length >= 2) sb.Length -= 2;

    return sb.ToString();
}

Пример использования:

// prints 0000012, 0000013, 0000014
Console.WriteLine( CreateRange("0000012-0000014") );
0

Я ожидаю, что ваша строка всегда будет иметь два целых числа, поэтому используйте Parse вместо TryParse

string[] strList = "48030-48039".Split('-').ToArray();

var lst = strList.Select(int.Parse).ToList();
var min = lst.OrderBy(l => l).FirstOrDefault();
var max = lst.OrderByDescending(l => l).FirstOrDefault();
var diff = max - min;

//adding 1 here otherwise 48039 will not be there
var rng = Enumerable.Range(min,diff+1);

Если вы ожидаете недопустимую строку

 var num = 0;
 var lst = (from s in strList where int.TryParse(s, out num) select num).ToList();
0

Вы это говорите?

int[] nums = new int[numArr.Length];
for (int i = 0; i < numArr.Length; i++)
{
    nums[i] = Convert.ToInt32(numArr[i]);
}
Array.Sort(nums);
for (int n = nums[0]; n <= nums[nums.Length - 1]; n++)
{
    Console.WriteLine(n);
}

здесь ссылка

-2
For Each item In Enumerable.Range(min, count).ToArray()
  something = item.PadLeft(5, "0")
Next
  • 1
    Именно то, что я думал, но это не C #
  • 0
    @Sayse: это правильно. Золотая звезда за ваши навыки наблюдения. Шутка в сторону, перевод на C # невероятно тривиален. Я уверен, что ОП способна.

Ещё вопросы

Сообщество Overcoder
Наверх
Меню