extension PartialSplit on String {
/// A version of [String.split] that limits splitting to return a [List]
/// of at most [count] items.
///
/// [count] must be non-negative. If [count] is 0, returns an empty
/// [List].
///
/// If splitting this [String] would result in more than [count] items,
/// the final element will contain the unsplit remainder of this [String].
///
/// If splitting this [String] would result in fewer than [count] items,
/// returns a [List] with only the split substrings.
List<String> partialSplit(Pattern pattern, int count) {
assert(count >= 0);
var result = <String>[];
if (count == 0) {
return result;
}
var offset = 0;
var matches = pattern.allMatches(this);
for (var match in matches) {
if (result.length + 1 == count) {
break;
}
if (match.end - match.start == 0 && match.start == offset) {
continue;
}
result.add(substring(offset, match.start));
offset = match.end;
}
result.add(substring(offset));
return result;
}
}
/// Prints a [List] of [String]s with less ambiguity.
///
/// The normal conversion of a `List<String>` to [String] would result in
/// ambiguity when printing `[]` and `['']`.
///
/// (Don't use this in production code. This does not escape embedded
/// quotes.)
void printStrings(List<String> strings) =>
print([for (var s in strings) "'$s'"]);
void main() {
// Prints: ['a', 'b', 'c d e']
printStrings('a b c d e'.partialSplit(' ', 3));
// Prints: ['a', 'b', 'c', 'd', 'e']
printStrings('a b c d e'.partialSplit(' ', 10));
// Prints: []
printStrings('a b c d e'.partialSplit(' ', 0));
// Prints: ['a', 'b', 'cde']
printStrings('abcde'.partialSplit('', 3));
// Prints: ['a b c d e']
printStrings('a b c d e'.partialSplit('_', 3));
// Prints: ['']
printStrings(''.partialSplit(' ', 3));
// Prints: ['', 'a', 'b c ']
printStrings(' a b c '.partialSplit(' ', 3));
// Prints: ['', 'a', 'b', '', 'c', '']
printStrings(' a b c '.partialSplit(' ', 10));
}
2条答案
按热度按时间cgyqldqp1#
自从
如果模式是一个字符串,那么它总是这样:
string.split(pattern).join(pattern) == string
因此,最简单的方法(假设您的示例是按固定字符而不是模式拆分)是重新连接剩余的元素:
或者如果你不喜欢临时子列表,而更喜欢迭代器:
然后你可以将列表构建为
[x, y, rem]
;通常,您可以按如下方式实现它:现在
split("a b c d e", ' ', 3)
将如所期望的那样是["a", "b", "c d e"]
。一个更有效的实现或一个支持模式的实现可能会用
start
参数集重复调用indexOf
,这可能是以简洁为代价的。zkure5ic2#
我不认为有任何内置的方法来限制
String.split
的结果数量。如果您在
String
上而不是在RegExp
上进行拆分,请注意String.split
documentation声明:如果模式是
String
,则总是这样:这意味着您可以执行
String.split
,获取所需的元素,然后对其余的元素使用join
,这可能会导致大量的工作浪费,因此效率不高。下面是一个限制最大元素数量的实现,它主要遵循C#语义: