# Lists Methods, Properties, and More! (Dart)

The `List` type is one of the most common data types that you will encounter in `Dart`; therefore, it is crucial to understand when and how to use the methods and properties of a `List`. I also highly recommend experimenting them in DartPad.

## Useful Methods

### 1. map()

The `map()` method produces a new list after transforming each element in the list. The following example performs addition to each number in the list.

``````void main() {
List<int> numbers = [1, 3, 5];
var transformedNumbers = numbers.map((number) => number + 2).toList();
print(transformedNumbers); // Output : [3, 5, 7]
}
``````

* Take note that `.map()` returns an Iterable so we have to convert it into a `List` using the `.toList()` method.

### 2. forEach()

The `forEach()` method is very similar to `map()` except that it doesn't produce a new list after running a function on each element.

``````void main() {
List<int> numbers = [1, 3, 5];
numbers.forEach((number) => print(number + 2));
}
/*
Output:
3
5
7
*/
``````

The `add()` method is used to add an element to the end of a list.

``````void main() {
List<int> numbers = [1, 3, 5];
print(numbers); // Output : [1, 3, 5, 7]
}
``````

### 4. removeAt()

The `removeAt` method removes an element from the list given a position `index`.

``````void main() {
List<int> numbers = [1, 3, 5, 7];
numbers.removeAt(2);
print(numbers); // Output: [1, 3, 7]
}
``````

### 5. where()

The `where()` method returns a list of elements that satisfy a certain test. Here's an example of a test that checks if a number is divisible by 2.

``````void main() {
List<int> numbers = [1, 4, 7, 10, 11];
var evenNumbers = numbers.where((number) => number % 2 == 0).toList();
print(evenNumbers); // Output: [4,10]
}
``````

* Take note that `.where()` returns an Iterable so we have to convert it into a `List` using the `.toList()` method.

### 6. firstWhere()

The `firstWhere()` method is very similar to `where()` except that it returns only the very first element that satisfy the test.

``````void main() {
List<int> numbers = [1, 4, 7, 10, 11];
var evenNumber = numbers.firstWhere((number) => number % 2 == 0);
print(evenNumber); /// Output: 4
}
``````

### 7. any()

The `any()` method returns true if at least one element satisfies the condition.

``````void main() {
const items = ['Beef', 'Broccoli', 'Banana'];
if (items.any((item) => item.contains('a'))) {
print('At least one of the elements contain the letter "a"');
}
//Output: At least one of the elements contain the letter "a"
}
``````

### 8. every()

The `every()` method returns true only if all of the elements satisfy the condition.

``````void main() {
const items = ['Beef', 'Broccoli', 'Banana'];
if (items.every((item) => item.contains('a'))) {
print('All elements contain the letter "a"');
}else{
print('Not all elements contain the letter "a"');
}
// Output: Not all elements contain the letter "a"
}
``````

## Useful Properties

### 1. length

The `length` property returns the length of a list.

``````void main() {
List<int> numbers = [72,243,859];
print(numbers.length); // Output: 3
}
``````

### 2. first

The `first` property returns the first element in the list.

``````void main() {
List<int> numbers = [72,243,859];
print(numbers.first); // Output: 72
}
``````

### 3. last

The `last` property returns the last element in the list.

``````void main() {
List<int> numbers = [72,243,859];
print(numbers.last); // Output: 859
}
``````

### 4. isEmpty

The `isEmpty` property returns `true` if the list has no elements.

``````void main() {
List<int> numbers = [];
print(numbers.isEmpty); // Output: true

print(numbers.isEmpty); // Output: false
}
``````

### 5. isNotEmpty

The `isNotEmpty` property returns `true` if the list has at least one element.

``````void main() {
List<int> numbers = [72,243,859];
print(numbers.isNotEmpty); // Output: true

numbers.clear(); // Removes all elements in the list
print(numbers.isNotEmpty); // Output: false
}
``````

## Bonus

### List.from()

The `List.from()` method creates a new list containing all of the elements from an existing list. To understand why we need to create a new list, take a look at the following scenario:

``````void main() {
List<int> oldNumbers = [1, 2, 3];
var newNumbers = oldNumbers;
print(oldNumbers); // Output: [1,2,3,4]
}
``````

The following code, `var newNumbers = oldNumbers`, creates a reference to the `oldNumbers` list. This is why when we added a number to `newNumbers`, that number is added to `oldNumbers`. In this scenario, both `newNumbers` and `oldNumbers` are referencing the same instance of a list.

#### Solution:

By making sure that `newNumbers` is referencing a new list, any changes to `newNumbers` will not affect `oldNumbers`.

``````void main() {
List<int> oldNumbers = [1, 2, 3];
var newNumbers = List.from(oldNumbers);