回答編集履歴

1

汎用化

2024/04/16 15:46

投稿

TN8001
TN8001

スコア9412

test CHANGED
@@ -60,3 +60,90 @@
60
60
  逆の場合はスマートな方法がありました。
61
61
  [Does C# have built-in support for parsing page-number strings? - Stack Overflow](https://stackoverflow.com/questions/40161)
62
62
  [c# - Convert range of number in string to list of integer - Stack Overflow](https://stackoverflow.com/questions/19889720)
63
+
64
+
65
+ ---
66
+
67
+ 文字列からだと汎用性がないのでintで受けるパターン(逆変換付き)
68
+ melianさんとBrian Payneさんのをまるパクリw
69
+
70
+ ```cs
71
+ using System.Diagnostics;
72
+ using System.Globalization;
73
+
74
+
75
+ for (var i = 0; i < 10; i++)
76
+ {
77
+ var numbers = Enumerable.Range(0, 30)
78
+ .OrderBy(x => Guid.NewGuid())
79
+ .Take(20)
80
+ .OrderBy(x => x)
81
+ .Take(Random.Shared.Next(20))
82
+ .ToList();
83
+
84
+ var rangeString = ToRangeString(numbers);
85
+ Console.WriteLine(rangeString);
86
+
87
+ var numbers2 = ParseRangeString(rangeString).ToList();
88
+ Console.WriteLine(string.Join(",", numbers2));
89
+ Console.WriteLine();
90
+
91
+ Debug.Assert(numbers.SequenceEqual(numbers2));
92
+ }
93
+
94
+
95
+ string ToRangeString(IEnumerable<int> source)
96
+ {
97
+ var r = source.Select((e, i) => (e, i))
98
+ .GroupBy(t => t.e - t.i, (k, tg) => tg.Select(t => t.e))
99
+ .Select((g, i) => $",{g.First()}{(1 < g.Count() ? $"~{g.Last()}" : "")}");
100
+
101
+ return string.Join("", r).TrimStart(',');
102
+ }
103
+
104
+ IEnumerable<int> ParseRangeString(string source)
105
+ {
106
+ if (string.IsNullOrWhiteSpace(source)) return [];
107
+
108
+ return source.Split(',')
109
+ .Select(x => x.Split('~'))
110
+ .Select(p => new
111
+ {
112
+ First = int.Parse(p.First(), CultureInfo.InvariantCulture),
113
+ Last = int.Parse(p.Last(), CultureInfo.InvariantCulture)
114
+ })
115
+ .SelectMany(x => Enumerable.Range(x.First, x.Last - x.First + 1));
116
+ }
117
+ ```
118
+
119
+ ```
120
+ 3,5,8~10
121
+ 3,5,8,9,10
122
+
123
+ 1,3,5~8,10~14,16~19,21
124
+ 1,3,5,6,7,8,10,11,12,13,14,16,17,18,19,21
125
+
126
+ 2
127
+ 2
128
+
129
+ 2~3,6~8,10~14
130
+ 2,3,6,7,8,10,11,12,13,14
131
+
132
+ 1~2,4~5,7~10
133
+ 1,2,4,5,7,8,9,10
134
+
135
+ 0~1,4~8,10,12,14,17
136
+ 0,1,4,5,6,7,8,10,12,14,17
137
+
138
+ 2~6
139
+ 2,3,4,5,6
140
+
141
+
142
+
143
+
144
+ 0,2~8,10,15,18,20~23
145
+ 0,2,3,4,5,6,7,8,10,15,18,20,21,22,23
146
+
147
+ 1~3,5~7,9~13,16~17,19,21~22,24,26
148
+ 1,2,3,5,6,7,9,10,11,12,13,16,17,19,21,22,24,26
149
+ ```