dart 将String.split限制为最大元素数

knsnq2tg  于 2023-04-18  发布在  其他
关注(0)|答案(2)|浏览(134)

在C#中,Split函数可以接收一个count参数,所以split返回最多count个元素:

var a = "a b c d e";
var r = a.Split(' ', 3);
// r is ["a", "b", "c d e"]

在Dart中实现这一点最简单的方法是什么?
我认为以下任何一项都是有用的:获得与所示完全相同的列表,或者获得不同变量中的3个元素。

cgyqldqp

cgyqldqp1#

自从
如果模式是一个字符串,那么它总是这样:string.split(pattern).join(pattern) == string
因此,最简单的方法(假设您的示例是按固定字符而不是模式拆分)是重新连接剩余的元素:

var x = r[0]; // a
var y = r[1]; // b
var rem = r.sublist(2).join(' '); // c d e

或者如果你不喜欢临时子列表,而更喜欢迭代器:

var rem = r.getRange(2, r.length).join(' '); // c d e

然后你可以将列表构建为[x, y, rem];通常,您可以按如下方式实现它:

split(String str, String sep, int n) {
    var list = str.split(sep);
    if (list.length <= n) return list;
    return [...list.getRange(0, n-1), list.getRange(n-1, list.length).join(sep)];
}

现在split("a b c d e", ' ', 3)将如所期望的那样是["a", "b", "c d e"]
一个更有效的实现或一个支持模式的实现可能会用start参数集重复调用indexOf,这可能是以简洁为代价的。

zkure5ic

zkure5ic2#

我不认为有任何内置的方法来限制String.split的结果数量。
如果您在String上而不是在RegExp上进行拆分,请注意String.split documentation声明:
如果模式是String,则总是这样:

string.split(pattern).join(pattern) == string

这意味着您可以执行String.split,获取所需的元素,然后对其余的元素使用join,这可能会导致大量的工作浪费,因此效率不高。
下面是一个限制最大元素数量的实现,它主要遵循C#语义:

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));
}

相关问题