我需要将一个数字分成均等的部分,例如:
32427237 需要变成 324 272 37
103092501 需要变成 103 092 501
如何分割它并处理奇数情况,如分割成这些部分,例如: 123 456 789 0?
我需要将一个数字分成均等的部分,例如:
32427237 需要变成 324 272 37
103092501 需要变成 103 092 501
如何分割它并处理奇数情况,如分割成这些部分,例如: 123 456 789 0?
如果您需要在代码中的多个位置执行此操作,则可以创建一个漂亮的扩展方法:
static class StringExtensions {
public static IEnumerable<String> SplitInParts(this String s, Int32 partLength) {
if (s == null)
throw new ArgumentNullException(nameof(s));
if (partLength <= 0)
throw new ArgumentException("Part length has to be positive.", nameof(partLength));
for (var i = 0; i < s.Length; i += partLength)
yield return s.Substring(i, Math.Min(partLength, s.Length - i));
}
}
然后您可以像这样使用它:
var parts = "32427237".SplitInParts(3);
Console.WriteLine(String.Join(" ", parts));
最终输出为324 272 37
,与期望相符。
当您将字符串分成部分时,即使这些子字符串已经存在于原始字符串中,也会分配新的字符串。通常情况下,您不必过于担心这些分配,但是使用现代 C#,您可以通过稍微修改扩展方法来使用“范围”来避免这种情况:
public static IEnumerable<ReadOnlyMemory<char>> SplitInParts(this String s, Int32 partLength)
{
if (s == null)
throw new ArgumentNullException(nameof(s));
if (partLength <= 0)
throw new ArgumentException("Part length has to be positive.", nameof(partLength));
for (var i = 0; i < s.Length; i += partLength)
yield return s.AsMemory().Slice(i, Math.Min(partLength, s.Length - i));
}
public static IEnumerable<ReadOnlyMemory<char>>
,并通过在源上调用Slice
创建子字符串,从而避免了分配。ReadOnlyMemory<char>
转换为用于API中的string
,则必须分配新的字符串。幸运的是,许多.NET Core API除了string
之外还使用ReadOnlyMemory<char>
,因此可以避免分配。this
关键字并适当重命名类和方法。我认为这个特定的方法非常通用(而不是特定于订单号之类的内容),是扩展方法的一个很好的候选。将类放在单独的命名空间中使开发人员能够决定是否启用扩展方法,就像添加using System.Linq
一样,可以向IEnumerable<T>
添加一堆扩展方法。 - Martin LiversageSystem.String
是类型名称,而string
是C#的别名。个人认为,在创建新标识符时,原始类型的正确类型名称效果更好。它是Object.ToString()
而不是Object.Tostring()
,以及Convert.ToInt64()
而不是Convert.Tolong()
。然而,大多数C#开发人员使用别名。 - Martin Liversagestring input = "12345678";
StringBuilder sb = new StringBuilder();
for (int i = 0; i < input.Length; i++)
{
if (i % 3 == 0)
sb.Append(' ');
sb.Append(input[i]);
}
string formatted = sb.ToString();
有一种非常简单的方法可以做到这一点(虽然不是最有效的,但也不比最有效的慢得多)。
public static List<string> GetChunks(string value, int chunkSize)
{
List<string> triplets = new List<string>();
while (value.Length > chunkSize)
{
triplets.Add(value.Substring(0, chunkSize));
value = value.Substring(chunkSize);
}
if (value != "")
triplets.Add(value);
return triplets;
}
public static List<string> GetChunkss(string value, int chunkSize)
{
List<string> triplets = new List<string>();
for(int i = 0; i < value.Length; i += chunkSize)
if(i + chunkSize > value.Length)
triplets.Add(value.Substring(i));
else
triplets.Add(value.Substring(i, chunkSize));
return triplets;
}
n
版本会更好。 - st0leString.Join(", ", GetChunks("20000", 3).ToArray())
将生成200, 00
,这对于货币是不正确的(应该是20, 000
),拆分应该从末尾开始。另外请注意,问题本身要求以这种方式拆分数字,这也是货币拆分不正确的原因。 - AaALINQ规则:
var input = "1234567890";
var partSize = 3;
var output = input.ToCharArray()
.BufferWithCount(partSize)
.Select(c => new String(c.ToArray()));
更新:
string input = "1234567890";
double partSize = 3;
int k = 0;
var output = input
.ToLookup(c => Math.Floor(k++ / partSize))
.Select(e => new String(e.ToArray()));
System.Linq.EnumerableEx.BufferWithCount
是 .NET (Rx) 反应式扩展的一部分:http://msdn.microsoft.com/en-us/devlabs/ee794896.aspx。您需要下载并安装此扩展程序,以使代码运行。 - Martin Liversageint n = 3;
string originalString = "32427237";
string splitString = string.Join(string.Empty,originalString.Select((x, i) => i > 0 && i % n == 0 ? string.Format(" {0}", x) : x.ToString()));
如果您知道整个字符串的长度恰好可以被部分大小整除,则使用以下方法:
var whole = "32427237!";
var partSize = 3;
var parts = Enumerable.Range(0, whole.Length / partSize)
.Select(i => whole.Substring(i * partSize, partSize));
但是如果有可能整个字符串末尾会有一个小数块,你需要更加复杂的处理方式:
var whole = "32427237";
var partSize = 3;
var parts = Enumerable.Range(0, (whole.Length + partSize - 1) / partSize)
.Select(i => whole.Substring(i * partSize, Math.Min(whole.Length - i * partSize, partSize)));
在这些示例中,parts将是一个IEnumerable,但是如果您想要一个string[]或List<string>值,可以在结尾处添加.ToArray()或.ToList()。
public static IEnumerable<string> SplitInGroups(this string original, int size) {
var p = 0;
var l = original.Length;
while (l - p > size) {
yield return original.Substring(p, size);
p += size;
}
yield return original.Substring(p);
}
要将字符串以空格为分隔符重新连接起来:
var joined = String.Join(" ", myNumber.SplitInGroups(3).ToArray());
编辑:我更喜欢Martin Liversage的解决方案 :)
编辑2:修复了一个错误。
编辑3:添加了代码以重新连接字符串。
public static string Format(string number, int batchSize, string separator)
{
StringBuilder sb = new StringBuilder();
for (int i = 0; i <= number.Length / batchSize; i++)
{
if (i > 0) sb.Append(separator);
int currentIndex = i * batchSize;
sb.Append(number.Substring(currentIndex,
Math.Min(batchSize, number.Length - currentIndex)));
}
return sb.ToString();
}
我喜欢这个因为它很酷,虽然不是特别高效:
var n = 3;
var split = "12345678900"
.Select((c, i) => new { letter = c, group = i / n })
.GroupBy(l => l.group, l => l.letter)
.Select(g => string.Join("", g))
.ToList();
试试这个:
Regex.Split(num.toString(), "(?<=^(.{8})+)");
(?<=_pattern_)
在匹配_pattern_后的点进行匹配。.{8}
匹配8个字符。因此,这应该从字符串开头匹配8、16、24、32等字符。但是我发现这个模式会重复输出第一组..? - FSCKur