How to filter nil values out of the collection types— Swift

Defensive coding is good coding.

Khemmachart Chutapetch
Panya Studios
7 min readFeb 5, 2019

--

Handling nil (null) value is something that every developer has to experience. No matter what language you are using or what platform you are developing, you have take care it very seriously. Otherwise it can and will cause problems to your application.

This article will talk about how to filter nil values out of collection types by Control-flow, Functional programming, and creating a classExtension for reusable code. I will summarise pros and cons for each methods at the end of this article.

1. Control flow

Control flow statements are provided by Swift. For examlple, for-loops to perform a task multiple times; for-in to iterate over arrays, dictionaries, and other sequences; if-else statements to execute different branches of code based on certain conditions.

Array

For example, let’s take a look at the following arrays: First one is nullable, and the second one is non-nullable

Our goal is to filter non-nil elements from optionalElements array and append it to filteredElements.

To achieve this, we will iterate through optionalElements for each element. There are two ways for gather a value. Let’s talk about the first way, force unwrapping i.e. if an element is not nil, then we will force it to non-optional type and append it to filteredElements. Else, continue.

Another way is called optional binding. It is more safe than using force unwrapping. It uses if-else statements to bind an optional type. See the following code below.

You can learn more about optional binding and force unwrapping from my Optional type article

Dictionary

Let’s assume that, we are going to build a dictionary from user payment data which is contain non-nil value and use it as a service parameters for service request body — Here is a struct where we store user payment data

Let assume that we displayed view to retrieve user payment data from an application. And this is data we got from a user.

As you can compare object properties to its class’s variables. Some of them are still contain no value (nil), such as, address, mobileNumber, gender. In this case, we should not send that nil value to a service. So we need to filter those properties when building a dictionary object — First idea to to assign only exist properties.

What do you think about this code? In my view, it not look pretty good. In term of code quality we call it duplicated code or hardcode . I am going to tell you how to prevent this kind of code.

2. Functional programming

Functional programming functions are provided by Apple. We can use these functions to reduce number of lines of code. It also easy to maintain and scale. We have no need to edit anything except making our struct to support one a new property, and store data to it.

Array

For an array collection, we can use both compactMap and filter. Depends on what result type are you expecting.

compactMap — is a generic instance Method which is returns an array containing the non-nil results of calling the given transformation with each element of this sequence. — Apple

In case you still want an array of optionals, you can use filter to remove nil elements. filter — is an instance method which is returns a new collection of the same type containing, in order, the elements of the original collection that satisfy the given predicate.

Dictionary

As we discuss above, we want to build a dictionary object to contain an key and non-nil values for service parameters. By that reasons, we have to unwrap all data before assign to dictionary to prevent nil value.

We can improve this flow of code by assign all data to dictionary either it is exist or nil. You can see the code below.

Now we have a dictionary which is contain optional string as a value, as you can see from its type[String: String?]. Then what we have to do is to remove nil out of it self. There are two ways to remove nil out of this dictionary, which arecontrol-flow and functional functions. Both case return non-nil.

Let start with the control-flow. We can use for-loop to iterate over dictionaries’ keys and then use if-else to help us unwrapping its value.

Or using functional programming function to return a non-nil value

This case is a combination of filter and mapValue. Now it look better in term for performance, we can reduce lines of code from control flow by using functional programming but I think this code look a little bit hard to understand. Our teammate might take a long to to understand how it works.

3. Collection Extension

A swift Extensions allows you to add functionality to an existing class, structure, enumeration, or protocol type. Extensions are similar to categories in Objective-C — Rather than using a global function or a method, we can create an extension to reduce duplicated code and make it more readable.

First problem with using this method is a generic type. Every times we call an array element or a dictionary value, it will return a generic type. We need to turn it to an optional type to check nil by create a new optional protocol and let optional conform that protocol.

Array

For an array type, we will add an extension to sequence collection which is contains elements as an optional type as you can see form where clauses. Then we write a methods to turn generic type to be optional type to check nil by using functional programing functions. If it is, then unwrap it

Example:

Dictionary

Same as array. We will add an extension to dictionary collection where its value is an optional type. Then we use the functional function to filter nil out of it values.

Example:

Conclusions

In the last session of this article, I will summarize the advantages and disadvantages for the usage of three methods we can use to filter nil values out of the collection types above.

Control-Flow

Using control-flow is easy to write as it is a basic pattern that every programmer should be familiar but it lead to duplicated code in your project. Let assume that you have a large scale project, how many control-flow you have to write to filter nil values? And it hard for maintenance and scale, if your data properties changes, it might affect to many places where are using that instance.

Functional programming

We can take the advantages of the functional programming concepts, such as, pure functions or immutable objects to make our to be more effective. It it can reduce our duplicated code. The only thing I concern is that, it might a little bit difficult to understand when someone review our code because the methods name does not implies how it works.

Collection extension

Extension is a very useful feature from Swift. We can reduce duplicated code by group it into a function. In additional, we can named the function to implies how it work to make our code to be more readable. There is no need to implement function body by using functional programming same as my example. As it might not suitable to your application behavior. But there is no doubt about using the extension!

Please share your idea or what do you think about filtering nil values out of a collection? However, this is my first English Technical article, please let me know if there are something wrong or not clear. I will be appreciated if your comment can improve my English and technical skill :)

References

Special thank to songtham tung to help me revise this article. He is a Full Stack Software Engineer who came from Silicon Valley. You can check out his awesome articles !!

--

--