What Is filter()?
filter() selects elements that pass a test (return True).
Without filter() (the old way):
numbers = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
even = []
for num in numbers:
if num % 2 == 0:
even.append(num)
print(even) # [2, 4, 6, 8, 10]
With filter() (elegant!):
numbers = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
even = list(filter(lambda x: x % 2 == 0, numbers))
print(even) # [2, 4, 6, 8, 10]
One line instead of a loop! 🚀
filter() Syntax
filter(predicate_function, iterable)
Parameters:
- predicate_function — must return True/False
- iterable — list, tuple, string, etc.
Returns: A filter object (convert it to a list)
result = filter(func, data) # filter object
result_list = list(filter(func, data)) # list
Basic Examples
1. Even numbers
numbers = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
even = list(filter(lambda x: x % 2 == 0, numbers))
print(even) # [2, 4, 6, 8, 10]
2. Odd numbers
numbers = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
odd = list(filter(lambda x: x % 2 != 0, numbers))
print(odd) # [1, 3, 5, 7, 9]
3. Above a threshold
numbers = [5, 12, 3, 18, 25, 7]
above_10 = list(filter(lambda x: x > 10, numbers))
print(above_10) # [12, 18, 25]
4. With a regular function
def is_positive(x):
return x > 0
numbers = [-5, 2, -3, 8, 0, -1, 10]
positive = list(filter(is_positive, numbers))
print(positive) # [2, 8, 10]
filter() with Strings
Filter by length
words = ["cat", "elephant", "mouse", "lion", "kangaroo"]
# Words longer than 4 characters
long_words = list(filter(lambda w: len(w) > 4, words))
print(long_words) # ['elephant', 'mouse', 'kangaroo']
# Short words
short_words = list(filter(lambda w: len(w) <= 4, words))
print(short_words) # ['cat', 'lion']
Filter by content
words = ["python", "javascript", "go", "java", "typescript"]
# Contain "script"
with_script = list(filter(lambda w: "script" in w, words))
print(with_script) # ['javascript', 'typescript']
# Start with "j"
starts_j = list(filter(lambda w: w.startswith("j"), words))
print(starts_j) # ['javascript', 'java']
Removing empty strings
data = ["Alice", "", "Bob", " ", "Charlie", ""]
# Remove empties
non_empty = list(filter(lambda s: s.strip(), data))
print(non_empty) # ['Alice', 'Bob', 'Charlie']
# OR just None (no lambda needed!)
non_empty2 = list(filter(None, data))
print(non_empty2) # ['Alice', 'Bob', ' ', 'Charlie'] ← spaces remain!
filter(None, …) removes only False, None, 0, and empty strings "". A string with spaces " " is truthy!
filter() with Dictionaries
Filter a list of dictionaries
students = [
{"name": "Alice", "grade": 95},
{"name": "Bob", "grade": 67},
{"name": "Charlie", "grade": 88},
{"name": "Dave", "grade": 72}
]
# Grade >= 80
high_performers = list(filter(lambda s: s["grade"] >= 80, students))
print(high_performers)
# [{"name": "Alice", "grade": 95}, {"name": "Charlie", "grade": 88}]
# Failed (< 70)
failed = list(filter(lambda s: s["grade"] < 70, students))
print(failed)
# [{"name": "Bob", "grade": 67}]
Filter dictionary keys
data = {"name": "Alice", "age": 25, "city": "New York", "score": 0}
# Remove keys with falsy values
filtered_keys = list(filter(lambda k: data[k], data.keys()))
print(filtered_keys) # ['name', 'age', 'city'] ← score=0 removed!
# Build a new dict
clean_data = {k: data[k] for k in filtered_keys}
print(clean_data) # {'name': 'Alice', 'age': 25, 'city': 'New York'}
Multiple Conditions
AND
numbers = [5, 12, 3, 18, 25, 7, 30]
# Even AND > 10
result = list(filter(lambda x: x % 2 == 0 and x > 10, numbers))
print(result) # [12, 18, 30]
OR
numbers = [5, 12, 3, 18, 25, 7, 30]
# < 10 OR > 20
result = list(filter(lambda x: x < 10 or x > 20, numbers))
print(result) # [5, 3, 25, 7, 30]
Complex conditions
products = [
{"name": "Phone", "price": 500, "in_stock": True},
{"name": "Laptop", "price": 1200, "in_stock": False},
{"name": "Mouse", "price": 25, "in_stock": True},
{"name": "Monitor", "price": 300, "in_stock": True}
]
# In stock AND price < 600
affordable = list(filter(
lambda p: p["in_stock"] and p["price"] < 600,
products
))
for p in affordable:
print(f"{p['name']}: ${p['price']}")
# Phone: $500
# Mouse: $25
# Monitor: $300
Practical Examples
Example 1: Email Filtering
emails = [
"alice@gmail.com",
"bob@yahoo.com",
"invalid-email",
"charlie@gmail.com",
"dave@hotmail.com"
]
# Gmail only
gmail_only = list(filter(lambda e: e.endswith("@gmail.com"), emails))
print(gmail_only) # ['alice@gmail.com', 'charlie@gmail.com']
# Contains @ and .
valid_emails = list(filter(lambda e: "@" in e and "." in e, emails))
print(valid_emails) # All except 'invalid-email'
Example 2: File Filtering
files = [
"image1.jpg",
"document.pdf",
"photo.png",
"script.py",
"data.csv",
"picture.jpg"
]
# Images only
images = list(filter(
lambda f: f.endswith(".jpg") or f.endswith(".png"),
files
))
print(images) # ['image1.jpg', 'photo.png', 'picture.jpg']
# Python files
python_files = list(filter(lambda f: f.endswith(".py"), files))
print(python_files) # ['script.py']
Example 3: Data Cleaning
raw_data = [0, 5, None, 12, "", False, 25, [], 30]
# Remove "falsy" values (0, None, "", False, [])
clean_data = list(filter(None, raw_data))
print(clean_data) # [5, 12, 25, 30]
# Only numbers > 0
numbers_only = list(filter(lambda x: isinstance(x, (int, float)) and x > 0, raw_data))
print(numbers_only) # [5, 12, 25, 30]
filter() vs List Comprehension
Both achieve the same result!
numbers = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
# filter()
even_filter = list(filter(lambda x: x % 2 == 0, numbers))
# List comprehension
even_comp = [x for x in numbers if x % 2 == 0]
print(even_filter == even_comp) # True
When to use which?
filter() — when:
- ✅ You already have a predicate function
- ✅ The condition is simple
- ✅ You prefer a functional style
def is_adult(person):
return person["age"] >= 18
adults = list(filter(is_adult, people))
List comprehension — when:
- ✅ The condition is complex
- ✅ You also need to transform the data
- ✅ Pythonic style
# Comprehension is more readable here
adult_names = [p["name"] for p in people if p["age"] >= 18]
Combining filter + map
filter → map: select first, then transform.
numbers = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
# Even → double
even = filter(lambda x: x % 2 == 0, numbers)
doubled = list(map(lambda x: x * 2, even))
print(doubled) # [4, 8, 12, 16, 20]
# OR in one line
result = list(map(lambda x: x * 2, filter(lambda x: x % 2 == 0, numbers)))
print(result) # [4, 8, 12, 16, 20]
map → filter: transform first, then select.
words = ["python", "go", "javascript", "c"]
# Uppercase → length > 2
upper = map(str.upper, words)
long_words = list(filter(lambda w: len(w) > 2, upper))
print(long_words) # ['PYTHON', 'JAVASCRIPT']
filter(None, …) — Special Case
filter(None, data) removes falsy values without a lambda!
data = [0, 1, False, True, None, "text", "", " ", [], [1, 2]]
filtered = list(filter(None, data))
print(filtered) # [1, True, 'text', ' ', [1, 2]]
What counts as falsy:
- ❌ None
- ❌ False
- ❌ 0, 0.0
- ❌ Empty: "", [], {}, ()
- ✅ Everything else is truthy
Useful for:
# Remove empty strings
lines = ["Line 1", "", "Line 2", None, "Line 3"]
non_empty = list(filter(None, lines))
print(non_empty) # ['Line 1', 'Line 2', 'Line 3']
# Remove zero scores
scores = [100, 0, 85, None, 92, 0]
valid_scores = list(filter(None, scores))
print(valid_scores) # [100, 85, 92]
Common Mistakes
Mistake 1: Forgot list()
numbers = [1, 2, 3, 4, 5]
result = filter(lambda x: x > 2, numbers)
print(result) # <filter object at 0x...> ← NOT a list!
# ✅ CORRECT
result = list(filter(lambda x: x > 2, numbers))
print(result) # [3, 4, 5]
Mistake 2: Predicate doesn’t return True/False
def check_bad(x):
x > 5 # Forgot return!
result = list(filter(check_bad, [1, 6, 3, 8]))
print(result) # [] ← Empty because the function returns None!
# ✅ CORRECT
def check_good(x):
return x > 5
result = list(filter(check_good, [1, 6, 3, 8]))
print(result) # [6, 8]
Mistake 3: Thinking filter modifies the original list
# filter does NOT modify the original list!
numbers = [1, 2, 3, 4, 5]
filtered = list(filter(lambda x: x > 2, numbers))
print(numbers) # [1, 2, 3, 4, 5] ← unchanged!
print(filtered) # [3, 4, 5] ← new list
Mistake 4: filter(None) doesn’t always behave as expected
data = [0, 5, 10, 15]
# filter(None) will remove 0!
result = list(filter(None, data))
print(result) # [5, 10, 15] ← 0 is gone!
# If 0 is a valid value, use a lambda
result = list(filter(lambda x: x is not None, data))
print(result) # [0, 5, 10, 15] ← 0 is kept
Performance
filter() is faster than a for loop on large datasets!
import time
data = list(range(1000000)) # One million numbers
# With a for loop
start = time.time()
result1 = []
for x in data:
if x % 2 == 0:
result1.append(x)
time_for = time.time() - start
# With filter
start = time.time()
result2 = list(filter(lambda x: x % 2 == 0, data))
time_filter = time.time() - start
print(f"For: {time_for:.4f}s")
print(f"Filter: {time_filter:.4f}s")
# filter is typically 10-20% faster!
Summary
filter() — what it does:
- ✅ Selects elements by condition
- ✅ The function must return True/False
- ✅ Returns a new collection
- ✅ Does NOT modify the original list
- ✅ Faster than a for loop
Syntax:
list(filter(predicate_function, data))
Typical usage:
# With lambda
list(filter(lambda x: x > 0, numbers))
# With a named function
list(filter(str.isupper, words))
# Remove falsy values
list(filter(None, data))
# Combined with map
list(map(str.upper, filter(lambda w: len(w) > 3, words)))
What’s Next?
Now you know filter()! 🎉
Next topics:
- reduce() — fold a list into a single value
- List comprehensions with if — an alternative to filter
- any() / all() — condition checks across a collection
filter() + map() = a powerful duo! 🚀
💬 Comments (0)
No comments yet
Be the first to share your opinion about this article!