You are currently viewing Fundamentals of Dart Lists: Everything You Need to Know

Fundamentals of Dart Lists: Everything You Need to Know

Dart is a powerful programming language that offers a rich set of features to build robust and scalable applications. One of the fundamental data structures in Dart is the List, which allows you to store and manipulate collections of objects. This article dives deep into the world of Dart Lists, covering everything you need to know, from basic operations to advanced concepts.

Table of Contents

What is a List?

A List in Dart is an ordered collection of objects that can grow or shrink dynamically. It allows you to store elements of any type, including other lists. Lists are zero-based indexed, meaning the first element is accessed using index 0, the second using index 1, and so on.

Declaring and Initializing Lists

To declare a List variable, you can use the List keyword followed by the desired type or use the generic type List<T>, where T represents the type of elements in the List. You can initialize a List using various approaches, such as the [] syntax, List.from() constructor et cetera.

void main() {

    // Using the list literal to create an empty list
    List<int> emptyList1 = [];

    // Using the List.empty() constructor to create an empty list
    List<int> emptyList2 = List.empty(growable: true);

    // Using the list literal to create a list of  programming languages
    List<String> languages = ['C', 'Dart', 'JavaScript', 'Swift', 'VB .NET'];

    // Using the List.filled() constructor to create a fixed-length list of
    // size 10, with each position filled with 0
    List<double> temperatures = List.filled(10, 0);

    // Using the List.generate() constructor to generate a list of even numbers
    List<int> evenNumbers = List.generate(10, (index) => index * 2);

    // Using List.from() constructor to create a list of numbers 1 through 10
    List<int> numbers = List.from([1, 2, 3, 4, 5, 6, 7, 8, 9, 10]);

    // Using the List.of() constructor to create a list of odd numbers
    List<int> oddNumbers = List.of([1, 3, 5, 7, 9, 11, 13, 15, 17, 19]);

    // Using the List.unmodifiable() constructor to create an unmodifiable list
    List<String> vowels = List.unmodifiable(['a', 'e', 'i', 'o', 'u']);
    
}

Accessing List Elements

List elements can be accessed using their corresponding indices. Dart provides the square bracket notation [] to retrieve elements by index. Additionally, you can use the first and last properties to access the first and last elements of a List, respectively.

Accessing elements using indices:

void main() {
  
  List<int> numbers = [1, 2, 3, 4, 5];

  // Accessing the number at index 0
  int fst = numbers[0];

  // Accessing the number at index 1
  int snd = numbers[1];

  // Print the numbers to the console
  print("The first number is ${fst}.");
  
  print("The second number is ${snd}.");
  
}

Accessing the first element using the first property:

void main() {
  
  List<int> numbers = [1, 2, 3, 4, 5];
  
  // Accessing the first number
  int fst = numbers.first;
  
  print("The first number is ${fst}.");
  
}

Accessing the last element using the last property:

void main() {
  
  List<int> numbers = [1, 2, 3, 4, 5];
  
  // Accessing the last number
  int lst = numbers.last;
  
  print("The last number is ${lst}.");
  
}

Modifying List Elements

Lists in Dart are mutable, allowing you to modify individual elements using their indices. By assigning a new value to a specific index, you can update the corresponding element. Dart also provides methods like replaceRange() and setRange() to modify multiple elements at once.

The example code provided demonstrates how to modify the value at a specific index using direct assignment:

void main() {

    List<int> numbers = List.from([1, 2, 3, 4, 5]);

    // Modify the value at index 4 to 50
    numbers[4] = 50;

    // Output: [1, 2, 3, 4, 50]
    print(numbers);

}

The replaceRange(int start, int end, Iterable<E> replacements) Method

This method replaces a range of elements in the list with elements from the given replacements iterable. The range of elements to be replaced starts at index start (inclusive) and ends at index end (exclusive). The replacements iterable can be of any type that extends E, which is the type of elements in the list.

Here’s an example that demonstrates the usage of replaceRange():

void main() {

    List<int> numbers = List.from([1, 2, 3, 4, 5]);

    numbers.replaceRange(1, 4, [6, 7, 8, 9]);
    
    // Output: [1, 6, 7, 8, 9, 5]
    print(numbers);

}

The setRange(int start, int end, Iterable iterable<E>, [int skipCount = 0]) Method

This method sets a range of elements in the list to the elements from the given iterable. The range of elements to be set starts at index start (inclusive) and ends at index end (exclusive). The iterable can be of any type that extends E. Additionally, you can specify an optional skipCount parameter, which determines the number of elements from the iterable to skip before starting the set operation.

Here’s an example that demonstrates the usage of setRange():

void main() {

    List<int> numbers = List.from([1, 2, 3, 4, 5]);

    numbers.setRange(1, 4, [6, 7, 8, 9]);

    // Output: [1, 6, 7, 8, 5]
    print(numbers);

}

Adding and Removing Elements

Dart offers several methods to add and remove elements from a List. The add() method allows you to append an element at the end, while insert() lets you add an element at a specific index. To remove elements, you can use methods like remove(), removeAt(), or removeLast().

The add(E element) Method

This method appends an element to the end of the list.

void main() {

    List<int> numbers = List.from([1, 2, 3, 4, 5]);

    numbers.add(10);

    // Output: [1, 2, 3, 4, 5, 10]
    print(numbers);

}

The insert(int index, E element) Method

This method inserts an element at the specified index in the list, shifting the existing elements to the right.

void main() {

    List<int> numbers = List.from([1, 2, 3, 4, 5]);

    numbers.insert(0, 0);

    // Output: [0, 1, 2, 3, 4, 5]
    print(numbers);

}

The remove(Object? element) Method

This method removes the first occurrence of the specified element from the list.

void main() {

    List<int> numbers = List.from([1, 2, 3, 4, 5]);

    numbers.remove(2);

    // Output: [1, 3, 4, 5]
    print(numbers);

}

The removeAt(int index) Method

This method removes the element at the specified index from the list.

void main() {

    List<int> numbers = List.from([1, 2, 3, 4, 5]);

    numbers.removeAt(1);

    // Output: [1, 3, 4, 5]
    print(numbers);

}

The removeLast() Method

This method removes the last element from the list.

void main() {

    List<int> numbers = List.from([1, 2, 3, 4, 5]);

    numbers.removeLast();

    // Output: [1, 2, 3, 4]
    print(numbers);
    
}

The addAll(Iterable<E> iterable) Method

The addAll() method appends all the elements from the specified iterable to the end of the list.

void main() {

    List<int> numbers = List.from([1, 2, 3, 4, 5]);

    numbers.addAll([6, 7, 8, 9, 10]);

    // Output: [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
    print(numbers);
    
}

The insertAll(int index, Iterable<E> iterable) Method

The insertAll() method inserts all the elements from the specified iterable starting at the specified index in the list, shifting the existing elements to the right.

void main() {

    List<int> numbers = List.from([1, 2, 3, 4, 5]);

    numbers.insertAll(0, [-5, -4, -3, -2, -1, 0]);

    // Output: [-5, -4, -3, -2, -1, 0, 1, 2, 3, 4, 5]
    print(numbers);

}

The removeWhere(bool test(E element)) Method

The removeWhere() method removes all elements from the list that satisfy the provided test function.

void main() {

    List<int> numbers = List.from([1, 2, 3, 4, 5]);

    numbers.removeWhere((element) => element % 2 == 0);
    
    // Output: [1, 3, 5]
    print(numbers);

}

The removeWhere() method is used to remove all even elements from the list. The test function (element) => element % 2 == 0 checks if an element is even, and if it is, that element is removed from the list.

List Length and Capacity

The length property of a List represents the current number of elements it contains. It can be used to get the length of the list or to explicitly resize the list.

To get the length of a List, you can use the length property as follows:

void main() {

    List<int> numbers = List.from([1, 2, 3, 4, 5]);
    
    int length = numbers.length;
    
    // Output: 5
    print('The numbers list holds $length elements.');

}

To explicitly resize a List, you can set the length property to a new value. If the new length is greater than the current length, the list will be extended with null values. If the new length is smaller, the list will be truncated.

void main() {

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

    // Output: [1, 2, 3]
    print(numbers);

    numbers.length = 7;

    // Output: [1, 2, 3, null, null, null, null]
    print(numbers);

}

If you need to increase the capacity of a List dynamically by adding elements from another iterable, you can use the addAll() method or the spread (…) operator.

The addAll() method adds all elements of an iterable to the end of the list:

void main() {

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

    List<int> moreNumbers = [6, 7, 8, 9, 10];

    numbers.addAll(moreNumbers);

    // Output: [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
    print(numbers);

}

The spread (…) operator allows you to concatenate multiple iterables together:

void main() {

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

    List<int> numbers2 = [6, 7, 8, 9, 10];

    List<int> numbers = [...numbers1, ...numbers2];

    // Output: [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
    print(numbers); 

}

It’s worth noting that Dart Lists automatically manage their capacity internally. As elements are added, the List automatically grows to accommodate them, and if elements are removed, the capacity is reduced accordingly. You don’t need to explicitly manage the capacity of a List in Dart.

List Iteration

Dart provides multiple ways to iterate over a List, such as using the traditional for loop, the forEach() method, or using the for-in loop. Each iteration method has its own benefits and can be chosen based on your specific requirements.

The For Loop

The traditional for loop allows you to iterate over a List using an index. You can specify the start and end index to control the iteration range. Here’s an example:

void main() {

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

    for (int i = 0; i < numbers.length; i++) {

        print(numbers[i]);
        
    }

}

The forEach() Method

The forEach() method is a concise way to iterate over each element of a List. It takes a callback function as an argument and executes that function for each element in the List. Here’s an example:

void main() {

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

    numbers.forEach((int number) {

        print(number);
        
    });

}

The For-in Loop

The for-in loop is used to iterate over each element in an iterable, including Lists. It automatically assigns each element to a loop variable. Here’s an example:

void main() {

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

    for (int number in numbers) {

        print(number);
        
    }

}

Iterator

Dart also provides an explicit Iterator class that allows you to iterate over a List manually. You can use the iterator property of a List to get an instance of the Iterator, and then use methods like moveNext() and current to iterate over the elements. Here’s an example:

void main() {

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

    while (iterator.moveNext()) {

        int number = iterator.current;
        
        print(number);

    }

}

Each iteration method has its advantages. The for loop gives you full control over the index, which can be useful in certain scenarios. The forEach() method provides a concise syntax for iterating over each element. The for-in loop is simpler and automatically assigns each element to a loop variable. The Iterator class offers the most flexibility but requires more manual control.

You can choose the iteration method based on the specific requirements of your code, such as the need for index manipulation, simplicity, or flexibility.

List Manipulation Methods

Dart offers various built-in methods for manipulating Lists. These methods include reversed, sublist, shuffle, fillRange, asMap, and more. Understanding these methods can greatly enhance your ability to work with Lists effectively.

The reversed Property

The reversed property returns a new List with the elements in reverse order. It does not modify the original List. Here’s an example:

void main() {

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

    List<int> reversedNumbers = numbers.reversed.toList();

    // Output: [5, 4, 3, 2, 1]
    print(reversedNumbers);
    
}

The sublist Method

The sublist method returns a new List that contains a portion of the original List based on the specified start and end indices. The start index is inclusive, and the end index is exclusive. Here’s an example:

void main() {

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

    List<int> subList = numbers.sublist(1, 4);
    
    // Output: [2, 3, 4]
    print(subList);

}

The shuffle Method

The shuffle method randomly shuffles the elements of the List. It modifies the original List in-place. Here’s an example:

void main() {

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

    numbers.shuffle();

    // Output: [random ordered list]
    print(numbers); 

}

The fillRange Method

The fillRange method replaces a range of elements in the List with a given value. It modifies the original List in-place. Here’s an example:

void main() {

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

    numbers.fillRange(1, 4, 0);

    // Output: [1, 0, 0, 0, 5]
    print(numbers);

}

The asMap Method

The asMap method returns a new Map where the keys are the indices of the List, and the values are the corresponding elements. Here’s an example:

void main() {

    List<String> languages = ['C', 'Dart', 'JavaScript', 'Python', 'Swift'];

    Map<int, String> languagesMap = languages.asMap();

    // Output: {0: C, 1: Dart, 2: JavaScript, 3: Python, 4: Swift}
    print(languagesMap);

}

These are just a few examples of the many useful List manipulation methods available in Dart.

Sorting and Searching Lists

Dart provides the sort() method to sort a List in ascending order. For custom sorting requirements, you can use the sort() method with a comparator function. To search for elements within a List, you can use methods like contains(), indexOf(), lastIndexOf(), where(), and any().

Sorting Lists

To sort a List in ascending order, you can use the sort() method:

void main() {

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

    numbers.sort();

    // Output: [1, 2, 3, 4, 5]
    print(numbers);

}

By default, the sort() method arranges the elements in ascending order using their natural ordering. For numeric or string lists, this results in the expected sorted sequence. However, for more complex objects, the sorting might not yield the desired results.

To perform a custom sort based on specific criteria, you can provide a comparator function to the sort() method:

class Person {

    String name;
    int age;

    Person(this.name, this.age);

}

void main() {

    List<Person> people = [

        Person('Jane', 25),
        Person('John', 30),
        Person('Edward', 28),

    ];

    // Sort people by age
    people.sort((a, b) => a.age.compareTo(b.age));

    // Output: [Jane, Edward, John]
    print(people.map((person) => person.name).toList());

}

We define a custom class Person with a name and age property. We sort the list of people based on their ages using a comparator function that compares the age property of two Person objects.

Searching Lists

Dart provides several methods to search for elements within a List:

The contains() Method

The contains() method checks if a given value is present in the List and returns a boolean result:

void main() {

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

    // Output: true
    print(numbers.contains(3));

}

The indexOf() and lastIndexOf() Methods

The indexOf() method returns the index of the first occurrence of a given value in the List. The lastIndexOf() method returns the index of the last occurrence:

void main() {

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

    // Output: 1
    print(numbers.indexOf(2));

    // Output: 3
    print(numbers.lastIndexOf(2));
    
}

The where() Method

The where() method returns a new Iterable containing all elements that satisfy a given condition. It allows you to filter elements from a List:

void main() {

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

    // Where the number is divisible by 2
    List<int> evenNumbers = numbers.where((number) => number % 2 == 0).toList();

    // Output: [2, 4]
    print(evenNumbers);

}

The any() Method

The any() method checks if any element in the List satisfies a given condition and returns a boolean result:

void main() {

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

    // Any number greater than 5?
    bool anyGreaterThanFive = numbers.any((number) => number > 5);

    // Output: false
    print(anyGreaterThanFive);

}

These methods provide powerful functionality for searching and filtering elements within a List, allowing you to perform operations based on specific conditions or criteria.

With the sorting and searching methods available in Dart, you can easily manipulate Lists, arrange them in the desired order, and search for specific elements efficiently. These methods are essential tools when working with collections and data manipulation in Dart.

List Equality

Dart does not include a built-in function to directly compare lists for equality. However, you can easily define your own function to accomplish this task. Here’s an example implementation of a listEquals() function:

bool listEquals<T>(List<T> list1, List<T> list2) {

    if (list1.length != list2.length) {
        return false;
    }

    for (int i = 0; i < list1.length; i++) {
        if (list1[i] != list2[i]) {
            return false;
        }
    }
    
    return true;

}

The listEquals() function takes two lists as parameters and compares them for equality. It first checks if the lengths of the lists are equal. If the lengths differ, it returns false since lists with different lengths cannot be equal. Next, it iterates over each element of the lists using a for loop and compares the corresponding elements. If any pair of elements is found to be unequal, the function returns false. Finally, if the lengths are equal and all corresponding elements are equal, the function returns true.

Let’s see the listEquals() function in action with a usage example:

void main() {

    List<int> list1 = [1, 2, 3];
    List<int> list2 = [1, 2, 3];
    List<int> list3 = [3, 2, 1];

    // Output: true
    print(listEquals(list1, list2));

    // Output: false
    print(listEquals(list1, list3));
    
}

Considerations and Limitations

When using the listEquals() function or any other custom implementation for comparing lists, keep in mind the following considerations:

Element Equality

The listEquals() function compares lists based on element equality. If the lists contain custom objects, ensure that the objects implement proper equality checks (e.g., overriding the == operator or implementing the hashCode method) for accurate results.

Shallow Comparison

The listEquals() function performs a shallow comparison, meaning that it compares elements by reference. If the lists contain objects, they will be considered equal only if their references are the same. If you need to perform a deep comparison (comparing the content of nested objects), you’ll need to implement additional logic.

Third-Party Libraries

If your project has more complex list comparison requirements, you might consider leveraging third-party libraries like collection or equatable. These libraries provide additional functionality, such as deep comparison, structural equality, or customizable comparison strategies.

Copying Lists

To create a shallow or deep copy of a List, you can use methods like toList(), sublist(), or the spread operator ….

The toList() Method

The toList() method creates a new list with the same elements as the original list. If you want to create a shallow copy (where the new list contains references to the same objects), you can use toList() directly. Here’s an example:

void main() {

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

    List<int> copiedList = originalList.toList();

    // Output: [1, 2, 3, 4, 5]
    print(originalList);

    // Output: [1, 2, 3, 4, 5]
    print(copiedList);

}

The sublist() Method

The sublist() method returns a new list that contains a portion of the original list. If you want to create a shallow copy of the entire list, you can use sublist(0). Here’s an example:

void main() {

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

    List<int> copiedList = originalList.sublist(0);
    
    // Output: [1, 2, 3, 4, 5]
    print(originalList);

    // Output: [1, 2, 3, 4, 5]
    print(copiedList);

}

The Spread Operator (…)

The spread (…) operator can also be used to create a copy of a list. It expands the elements of the original list into a new list. Here’s an example:

void main() {

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

    List<int> copiedList = [...originalList];

    // Output: [1, 2, 3, 4, 5]
    print(originalList);

    // Output: [1, 2, 3, 4, 5]
    print(copiedList);

}

These methods allow you to create copies of lists in Dart. However, it’s important to note that these methods create shallow copies, meaning that they copy the references to the objects rather than creating new objects. If the elements of the list are objects, changes to the objects in one list will be reflected in the other list.

If you need to create a deep copy (where new objects are created) for lists that contain objects, you’ll need to perform a custom copy operation. This typically involves iterating over the original list, creating new objects, and populating the new list with the copied objects.

List Spreading and Cascade Notation

Dart provides the spread operator … to concatenate or spread the elements of one List into another. This operator is useful for combining Lists or adding elements from one List to another. Additionally, Dart’s cascade notation allows you to chain multiple operations on a List.

List Spreading with the Spread Operator

The spread operator (…) allows you to concatenate or spread the elements of one list into another. It simplifies the process of combining lists or adding elements from one list to another. Here are some examples:

void main() {

    List<int> list1 = [1, 2, 3];
    List<int> list2 = [4, 5, 6];

    // Concatenate lists using the spread operator
    List<int> concatenatedList = [...list1, ...list2];

    // Output: [1, 2, 3, 4, 5, 6]
    print(concatenatedList);

    // Add elements from one list to another
    List<int> targetList = [7, 8, 9];
    targetList.addAll([...list1, ...list2]);

    // Output: [7, 8, 9, 1, 2, 3, 4, 5, 6]
    print(targetList);
    
}

The spread operator is used to spread the elements of list1 and list2 into a new list (concatenatedList) or into an existing list (targetList) using the addAll() method. The result is a single list containing all the elements from the original lists.

Cascade Notation for Chaining Operations

Dart’s cascade notation (..) allows you to chain multiple operations on a list without repeating the list name. It provides a concise and readable way to perform a series of operations on the same list. Here’s an example:

class Person {

    String name;
    int age;

    Person(this.name, this.age);

    void celebrateBirthday() {

        age++;

        print('Happy birthday, $name! You are now $age years old.');

    }

}

void main() {

    List<Person> people = [
        Person('Jane', 25),
        Person('John', 30),
        Person('Edward', 28),
    ];

    people
        ..forEach((person) => person.celebrateBirthday())
        ..sort((a, b) => a.age.compareTo(b.age));

    // Output: [Jane (26), Edward (29), John (31)]
    print(people.map((person) => '${person.name} (${person.age})').toList());
    
}

The cascade notation (..) is used to chain two operations on the people list. The forEach() method is used to invoke the celebrateBirthday() method on each Person object, and then the sort() method is used to sort the list based on the age property.

By using cascade notation, you can perform multiple operations on the same list in a concise and readable manner.

Working with Nested Lists

Dart Lists can be nested, meaning you can have Lists within Lists. This enables you to create multi-dimensional data structures. We’ll explore how to access, modify, and iterate through nested Lists.

Accessing Elements in Nested Lists

To access elements in a nested list, you can use multiple index operators ([]) to traverse through each level of nesting. Here’s an example:

void main() {

    List<List<int>> nestedList = [
        [1, 2, 3],
        [4, 5, 6],
        [7, 8, 9],
    ];

    int element = nestedList[1][2];

    // Output: 6
    print(element);

}

In the above example, nestedList is a list of lists. To access an element, we use two index operators: the first index selects the sub-list, and the second index selects the element within that sub-list.

Modifying Elements in Nested Lists

You can modify elements in nested lists in a similar manner. Use index operators to access the desired element and assign a new value to it. Here’s an example:

void main() {

    List<List<int>> nestedList = [
        [1, 2, 3],
        [4, 5, 6],
        [7, 8, 9],
    ];

    nestedList[1][2] = 10;
    
    // Output: [[1, 2, 3], [4, 5, 10], [7, 8, 9]]
    print(nestedList);
    
}

In the above example, we modify the element at index [1][2] (i.e., row 1, column 2) to have a new value of 10.

Iterating Through Nested Lists

To iterate through a nested list, you can use nested loops. The outer loop iterates through the sub-lists, and the inner loop iterates through the elements within each sub-list. Here’s an example:

void main() {

    List<List<int>> nestedList = [
        [1, 2, 3],
        [4, 5, 6],
        [7, 8, 9],
    ];

    for (int i = 0; i < nestedList.length; i++) {

        for (int j = 0; j < nestedList[i].length; j++) {

            print(nestedList[i][j]);

        }

    }

}

The above code prints each element in the nested list. It uses two nested loops to iterate over each sub-list and then each element within each sub-list.

You can also use higher-order functions, such as forEach() or map(), in combination with nested lists to perform operations on the elements. Here’s an example using forEach():

void main() {

    List<List<int>> nestedList = [
        [1, 2, 3],
        [4, 5, 6],
        [7, 8, 9],
    ];

    nestedList.forEach((subList) {

        subList.forEach((element) {

            print(element);

        });

    });
    
}

In this example, forEach() is used to iterate over each sub-list and then each element within each sub-list, printing the elements.

Working with nested lists in Dart allows you to create complex data structures and perform operations on the nested elements. By understanding how to access, modify, and iterate through nested lists, you can work with multi-dimensional data effectively.

Lists as Function Parameters

Lists are often used as function parameters to pass collections of values. We’ll discuss how to define functions that accept Lists as arguments and explore different approaches to pass Lists.

Defining Functions with List Parameters

To define a function that accepts a list as a parameter, you can specify the type of the list using angle brackets <>. Here’s an example:

void printList(List<int> numbers) {

    for (int number in numbers) {

        print(number);

    }
}

The function printList takes a list of integers (List) as its parameter. It iterates through the list and prints each element.

Approaches to Pass Lists to Functions

There are several approaches to pass lists to functions in Dart:

Positional Arguments

You can pass a list as a positional argument by simply providing the list when invoking the function:

void printList(List<int> numbers) {

    for (int number in numbers) {

        print(number);

    }
}

void main() {

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

    printList(numbers);

}

In this case, the numbers list is passed as a positional argument to the printList function.

Named Arguments

You can also pass a list as a named argument by specifying the name of the parameter when invoking the function:

void printList({required List<int> numbers}) {

    for (int number in numbers) {

        print(number);

    }

}

void main() {

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

    printList(numbers: numbers);

}

In this approach, the numbers list is passed as a named argument to the printList function.

Choose the appropriate approach based on your specific use case and the requirements of the function you are calling.

Mixed Argument Lists

In addition to passing a list as an argument, you can also mix it with other positional or named arguments in a function call. Here’s an example:

void printListWithMessage(List<int> numbers, {String message = ''}) {

    print(message);

    for (int number in numbers) {

        print(number);

    }

}

void main() {

    List<int> numbers = [1, 2, 3, 4, 5];
    
    printListWithMessage(numbers, message: 'Printing Numbers:');

}

The function printListWithMessage accepts both a list of integers (numbers) and an optional named argument (message). The list is passed as a positional argument, while the message is passed as a named argument with a default value.

Defining Functions that Return Lists

To define a function that returns a list, you need to specify the return type as List<T>, where T represents the type of elements in the list. Here’s an example:

List<int> generateEvenNumbers(int n) {

    List<int> numbers = [];

    for (int i = 2; i <= n; i += 2) {

        numbers.add(i);

    }

    return numbers;

}

The generateEvenNumbers() function takes an integer n as an input parameter and returns a list of even numbers up to n. It uses a for loop to generate even numbers and adds them to the numbers list. Finally, the list is returned as the function’s result.

Approaches to Return Lists from Functions

There are different approaches to return lists from functions in Dart:

Return List Variable

The simplest approach is to create a list variable, populate it with the desired elements, and return the list using the return statement. Here’s an example:

List<int> generateEvenNumbers(int n) {

    List<int> numbers = [];

    for (int i = 2; i <= n; i += 2) {

        numbers.add(i);

    }

    return numbers;

}

In this case, the numbers list is populated within the function, and then it is returned as the result.

Return List Literal

Dart allows you to return a list literal directly from a function without assigning it to a variable. Here’s an example:

List<int> generateEvenNumbers(int n) {
    
    return [for (int i = 2; i <= n; i += 2) i];
    
}

In this approach, the list literal [for (int i = 2; i <= n; i += 2) i] is returned directly from the function. It utilizes a collection for loop to generate the even numbers and returns the resulting list.

Choose the appropriate approach based on your specific use case and the requirements of the function.

Usage Example

Let’s use the generateEvenNumbers() function from the previous example to generate a list of even numbers and print them:

void main() {

    List<int> numbers = generateEvenNumbers(10);

    print(numbers);

}

In this example, the generateEvenNumbers() function is called with 10 as the argument, and the returned list of even numbers is assigned to the numbers variable.

Conclusion

We covered the fundamentals of Dart Lists. We explored various aspects of List manipulation, element access, iteration, sorting, searching, copying, and more. By mastering these concepts, you’ll have a solid foundation for working with Lists in Dart and building powerful applications.

Dart’s List data structure provides immense flexibility and functionality, making it an essential tool for any Dart developer.

Related Links:

I hope you found this information informative. If you would like to receive more content, please consider subscribing to our newsletter!

Leave a Reply