Flutter - 检查列表中是否存在索引

Sha*_*gin 13 dart flutter

假设我有一个列表:

List<int> numbers = [1, 2, 3, 4, 5,];
Run Code Online (Sandbox Code Playgroud)

如何检查列表中的对象是否存在于某个索引处??

例如

if (numbers[6] != null) {
  print('Exists');
}
Run Code Online (Sandbox Code Playgroud)

我希望我可以这样做,但显然它不起作用。

Abi*_*n47 18

我对其他提供的答案感到困惑。从问题文本来看,所有这些辅助函数和列表到地图的转换等等都是极端的矫枉过正。简单的if检查有什么问题?

var list = [1, 2, 3, 4, 5];
var index = 4;
var value = 5;

if (list.length > index && list[index] == value) {
  ...
}
Run Code Online (Sandbox Code Playgroud)

优雅在于简单,而不在于某种代码格式。将列表转换为地图需要工作,并且您复制数据,这完全是毫无理由的。如今,代码可读性通常比性能更重要,但没有理由使用一种明知可怕的做法来获得如此最小的外观收益。

即使上面的方法真的让你很烦恼,你总是可以把它包装在一个扩展方法中:

extension ListExtensions<T> on List<T> {
  bool containsAt(T value, int index) {
    assert(this != null);
    return index >= 0 && this.length > index && this[index] == value;
  }
}

// Usage

var list = [1, 2, 3, 4, 5];
var index = 4;
var value = 5;

if(list.containsAt(value, index)) {
  ...
}
Run Code Online (Sandbox Code Playgroud)

编辑:array.indicesSwift 中的字段是 a Range,并且调用contains检查值是否在该范围内。由于工作方式Range,检查一个值是否在其中是一个恒定时间的操作,这就是它如此高效的原因。事实上,Swift 中的以下方法或多或少地执行相同:

let array = [1, 2, 3, 4, 5]
let idx = 2

// array.indices approach
if array.indices.contains(idx) {
  ...
}

// Manual check approach
if idx >= 0 && idx < array.count {
  ...
}
Run Code Online (Sandbox Code Playgroud)

Flutter 没有该Range类型,因此尝试执行代码杂技以获取等效的代码会导致简单地检查列表中是否存在索引的效率极低。例如,以下list.asMap().contains(idx)是所选答案中的方法与其等价的纯代码方法之间的比较:

var list = [1, 2, 3, 4, 5];
var idx = 2;

// asMap approach
if (list.asMap().containsKey(idx)) {
  ...
}

// Manual conversion and check approach
Map<int, int> map = {};
for (var i = 0; i < list.length; i++) {
  map[i] = list[i];
} 
if (map.containsKey(idx)) {
  ...
}
Run Code Online (Sandbox Code Playgroud)

如您所见,将列表转换为 aMap是一个线性过程,而不是一个常数,因此如果列表很长,这可能需要很长时间。不仅如此,您最终创建了一个完全冗余的Map对象,该对象包含列表的所有元素以及作为其键的索引,因此您的内存占用量实际上增加了一倍(甚至考虑到映射存储这两个键时甚至增加了两倍)和价值)。希望您能明白为什么这种检查列表是否包含索引的方法在各方面都比“正常”方式更糟糕。(并且在评论中他建议打电话asMap 两次????


然而Range,Swift 中的类型在 Dart 中并不难制作,并且使用上面的扩展方法方法,您可以获得相同的语法和性能:

(范围.dart)

class Range extends Iterable<int> {
  const Range(this.start, this.end) : assert(start <= end);
  const Range.fromLength(int length) : this(0, length - 1);

  final int start;
  final int end;

  int get length => end - start + 1;

  @override
  Iterator<int> get iterator => Iterable.generate(length, (i) => start + i).iterator;

  @override
  bool contains(Object? index) {
    if (index == null || index is! int) return false;
    return index >= start && index <= end;
  }

  @override
  String toString() => '[$start, $end]';
}
Run Code Online (Sandbox Code Playgroud)

(list_extensions.dart)

import 'range.dart';

extension ListExtensions on List {
  Range get indices => Range.fromLength(this.length);
}
Run Code Online (Sandbox Code Playgroud)

(main.dart)

import 'list_extensions.dart';

main() {
  final list = [1, 2, 3, 4, 5];
  print(list.indices);              // [0, 4]
  print(list.indices.contains(3));  // true
  print(list.indices.contains(5));  // false
  print(list.indices.contains(-1)); // false
}
Run Code Online (Sandbox Code Playgroud)

说了这么多,你的问题的第二个方面不会被这个覆盖,你仍然需要检查索引本身的值。(请注意,您也必须在 Swift 中执行此操作)

if (list.indices.contains(index) && list[index] == value) {
  // `value` exists in the list at `index`
  ...
}
Run Code Online (Sandbox Code Playgroud)


Car*_*yes 13

您可以将Lista转换为 aMap并检查密钥:

List<int> numbers = [1, 2, 3, 4, 5,];

//Check if index 7 is valid
if (numbers.asMap().containsKey(7)) {
  print('Exists');
} else {
  print('Doesn\'t exist');
}

//[EDIT] Check if item at index 4 exists and is 5
if (numbers.asMap()[4] == 5) {
  print("Index 4 = 5");
} else {
  print("Index 4 != 5");
}
Run Code Online (Sandbox Code Playgroud)

  • 确实如此,直到您使用超出范围的索引。在这个例子中 `(numbers[9] == 5)` 将触发异常,但 `(numbers.asMap()[9]==5)` 将返回 false。 (2认同)