假设我有一个列表:
List<int> numbers = [1, 2, 3, 4, 5,];
如何检查列表中的对象是否存在于特定索引?
例如:
if (numbers[6] != null) {
print('Exists');
}
我本来希望可以做类似那样的事情,但显然它不起作用。
List
转换为Map
并检查键: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");
}
if(numbers[4] == 5)
。 - Crazy Lazy Cat(numbers[9] == 5)
将触发一个异常,但是(numbers.asMap()[9]==5)
将返回false。 - Carlos Javier Córdova Reyesif (numbers.asMap()[10] == null)
怎么样?在你的情况下它不会起作用。 - mezoniif ((numbers.asMap().containsKey(10)) && (numbers.asMap()[10] == null))
。 - Carlos Javier Córdova Reyes我对其他提供的答案感到困惑。从问题文本来看,所有这些辅助函数和将列表转换为映射等操作都是过度的杀伤力。用一个简单的if
检查有什么问题吗?
var list = [1, 2, 3, 4, 5];
var index = 4;
var value = 5;
if (list.length > index && list[index] == value) {
...
}
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)) {
...
}
编辑:在 Swift 中,array.indices
字段是一个 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 {
...
}
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)) {
...
}
Map
是一个线性过程,而不是一个恒定的过程,因此如果列表很长,这可能需要相当长的时间。不仅如此,您还会创建一个完全多余的Map
对象,该对象包含列表的所有元素以及索引作为其键,因此您实际上已经将内存占用量增加了一倍(或甚至三倍,考虑到映射同时存储键和值)。希望您能看出,相对于“正常”方式,检查列表是否包含索引的这种方法在各方面都更差。(并且在评论中,他建议调用 asMap
两次???)
Range
类型并不那么难,使用上述扩展方法的方法,您可以实现完全相同的语法和性能: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]';
}
(list_extensions.dart)
import 'range.dart';
extension ListExtensions on List {
Range get indices => Range.fromLength(this.length);
}
(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
}
if (list.indices.contains(index) && list[index] == value) {
// `value` exists in the list at `index`
...
}
array.indices.contains(index)
而不是检查数组长度。所以,带有.containsKey(index)
的map答案对我来说更加熟悉。我同意它会做一些不必要的额外工作。那么我的问题是,为什么在Flutter中不能像在Swift中那样访问列表的索引。难道Swift在幕后也执行了相同的列表到映射转换工作吗? - Shalugin有一个强大的原生包用于处理集合,在解决这个问题的同时,您可以在其中找到很多有趣的东西。
import 'package:collection/collection.dart';
...
List<int> numbers = [1, 2, 3, 4, 5,];
int element = numbers.firstWhereIndexedOrNull((i, _) => i == 6);
if (element != null) {
print('Exists');
}
firstWhereOrNull
,因为它可以清理掉我的代码中的许多一次性函数,就像其他建议一样。 - Nick N方法1
List<int> numbers = [1, 2, 3, 4, 5,];
int index = 3,find = 4;
//case 1
if(index<numbers.length && numbers[index] == find)
print('$find exists at index $index');
else
print('$find not found at index $index');
//case 2
index = 7;
if(index<numbers.length &&numbers[index] == find)
print('$find exists at index $index');
else
print('$find not found at index $index');
int index = 3, find = 4, foundAt;
foundAt = numbers.indexOf(find);
//case 1
if (index == foundAt)
print('Index of $find is $foundAt');
else
print('Value not found at $index');
//case 2
index = 7;
if (index == foundAt)
print('Index of $find is $foundAt');
else
print('Value not found at $index');
最简单的方法是 =>
List<int> numbers = [1, 2, 3, 4, 5,];
if ($(numbers,6) != null) {
print('Exists');
}
var isIndexValid = array.asMap().containsKey(index)
的意思是判断数组array
是否包含索引为index
的值,并将结果赋值给变量isIndexValid
。 - Crazy Lazy Cat