Filter an Array in Go

Jeff Roberts
InstructorJeff Roberts
Share this video with your friends

Social Share Links

Send Tweet

Golang has no built-in function(s) to filter an array. This lesson will teach you two different ways to filter.

The first is to create a separate array and add the filtered elements to it. This works great, but doesn't use memory as efficiently as the second way.

The second way shows you how to filter by altering the original array in place without making another array to hold the filtered elements. But, it has a side-effect that I'll tell you about which may help you decide which approach you will use to filter your array.

Instructor: [0:00] Let's start by loading some data into an array from a file. Here, I call a function called loadChampions. If it errors out, I'll log something. Otherwise, I am going to log the entire array to the console.

[0:13] Let's run that and take a look at what I've got. You can see here that there's a bunch of data. 56 total elements in this array, which I'll talk about here in a sec.

[0:24] Let's take a closer look at the data that I am working with. I have this file called tft.champions.json. As you can see, it's a JSON structure, which is an array containing a bunch of things which are champions from a game I love to play called the Teamfight Tactics.

[0:43] Next, let's see how I am representing this in memory. I have these champion struct that contains a name -- which is the name of the champion -- an array of classes, each champion belongs to one or more classes. Same for origin, each champion belongs to one or more origin and has a goal cost.

[1:04] Go has no built-in functionality for filtering arrays. The first thing I want to do is create an alias called the filterFunc, which is simply a func that accepts the champion and returns a Boolean.

[1:21] Next, I am going to create a function called the filter, which is a function that accepts an array of champions, and a filter func, which I have aliased below, and returns a filtered list of champions.

[1:39] The first thing I am going to do is to create an empty array called filtered, which will contain the list of champions that are filtered.

[1:51] I am going to iterate over each of these champions that were passed in. For each one, I am going to call the filtered function passing the champion. If that returns true, I am going to add that filtered champion to the list of filtered champions that I am collecting as we go along.

[2:18] We use the append function including the array we want to add it to and the thing that we want to add. When we're done, all I want to do is return the filtered list.

[2:36] Let's use this to filter the array. I have a problem there. Let me fix that.

[2:41] The first thing I am going to do is go up here to my func and create a new variable called brawlers. That's going to hold the result of calling our filter function down here, passing the list of champions that we loaded from the file and an anonymous function, which accepts a champion, which we'll call champ, and returns a Boolean.

[3:07] This initial implementation is going to be very simple. We're going to return all brawlers. Brawlers are a class of champions, so we're going to say champ.hazclassbrawler. That's as easy as it gets. Let's see what our filter did.

[3:28] We have brawlers now. Let's print those out, and we're going to print how many brawlers we found and the list of brawlers. Let's put a little extra spacing in there, so we have the link first, and then the brawlers themselves. Let's run this. We can see here that the first thing we print out is the filtered list of brawlers. You'll notice that out of these 56 total champions, we filtered just to include only the brawlers. These are anything with a brawler class.

[4:11] Now that I've got this, let me show you that I can alter this anonymous filter func to add some additional criteria. Let's say I only want brawlers that cost more than three gold. I can simply add that into my filter func, and this will still return a Boolean.

[4:31] It must be a brawler, and the cost must be greater than or equal to three. Let's run that, and we can see there are only three brawlers in the entire list of 56 champions that cost three gold or more. You can see here, we have the brawler class in each of these champions, as well as the gold cost for three and three.

[4:53] I've shown you one way to filter an array, but there's another and maybe better way, depending upon your individual situation. To illustrate this better, I'm going to copy this log line, printing out the original list of champions loaded from the file first, before I filter.

[5:11] Let's run that again. We're not really going to see anything noteworthy here, other than you'll see the original list before I call filter. Acali and Evelyn are the first two champions. Then we call filter, which results in our expensive brawlers, and then I print out the original list again, which has the unaltered Acali, Evelyn, the same one that I loaded from the file.

[5:37] The second way that I'm going to show you is more efficient, but it has a side effect. What I'm going to do here, instead of creating a copy, another array, is I'm going to alter the original array in-place. This requires a little bit different technique. If the filter func returns true, I'm going to alter the original array in-place and increment the counter of the found filtered champions.

[6:09] Then instead of returning this new array, I'm going to return a slice, which is a view of the underlying array, up to the count that I found. Let's see what this does. When I run this, you'll notice that here's the original list of 56 champions.

[6:33] Acali and Evelyn are first, then my filter, which works just like the previous technique. However, after I filtered, you'll notice that this original array has been altered. Cho-gath is first, followed by Vy. No longer is it Acali or Evelyn.

[6:53] This has a side effect of altering the original array. If you don't need it after you filter it, then this is the more efficient way.