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
Это должно работать с вашим основным нулевым требованием:
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();
Несколько замечаний:
List<int>
в концеlong
для обслуживания более длинных номеров, остерегайтесь того, что максимальное число, которое будет анализироваться, равно 9,223,372,036,854,775,807
, вы можете удвоить это значение (не длина), используя ulong
Полное решение, вдохновленное ответом @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();
}
}
В комментариях были затронуты три существенных вопроса:
Номера телефонов имеют достаточно цифр, чтобы превышать Int32.MaxValue
поэтому преобразование в int
не является жизнеспособным.
Номера телефонов могут иметь ведущие нули (предположительно для некоторых международных звонков?)
Возможный диапазон чисел может теоретически превышать максимальный размер массива (который может иметь проблемы с памятью, и я думаю, что он не может быть представлен как 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");
Это один из способов сделать это:
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(); ;
}
Вы можете использовать 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") );
Я ожидаю, что ваша строка всегда будет иметь два целых числа, поэтому используйте 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();
Вы это говорите?
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);
}
For Each item In Enumerable.Range(min, count).ToArray()
something = item.PadLeft(5, "0")
Next
long
, но теперь мне интересно, слишком ли велики диапазоны в этом случае, чтобы их можно было использовать; мы можем использовать отсроченное исполнение здесь.