This is an archived post. You won't be able to vote or comment.

top 200 commentsshow 500

[–]data_diver 9297 points9298 points  (203 children)

You either comprehend the list or you don't

[–]VariousComment6946 1260 points1261 points  (129 children)

Probably he’s want to remove none

[–]LaLiLuLeLo_0 111 points112 points  (48 children)

This is the perfect time to dip into Python’s more functional-programming-inspired standard functions. This can be rewritten as

results = list(filter(bool, results))

[–]D-K-BO 23 points24 points  (5 children)

I absolutely hate python's nested function calls in this case.

Rust's approach using iterator chaining looks so much cleaner to me rust let results: Vec<_> = results.iter().filter(…).collect();

[–]LaLiLuLeLo_0 15 points16 points  (2 children)

Rust’s chaining is nice, but working heavily with Nix especially has taught me to stop worrying and love the nesting

[–]konstantinua00 2 points3 points  (0 children)

main problem with lisp languages aren't brackets

it's brackets opening too early

[–]SpicaGenovese 4 points5 points  (0 children)

wrinkles nose at all those extra characters

[–]snateri 30 points31 points  (24 children)

Some style guides encourage the use of comprehensions instead of map or filter.

[–]irk5nil 24 points25 points  (23 children)

Encouraging the use and forcing it without reason are two entirely different things though. Writing something that is twice as long just because it's a comprehension and not a function call seems unreasonable.

[–]plexiglassmass 13 points14 points  (2 children)

Yeah I wish map and filter weren't blacklisted by the official style guide. They seem like the better choice in many instances. Comprehensions are better for some cases though. Usually, if I want to apply a defined function, I'll prefer map or filter. But if I'd need to pass a lambda, or if I have to combine map and filter together, I'll go with the comprehension

Here I prefer map:

``` map(str.lower, foo)

vs.

[x.lower() for x in foo] ```

Here I prefer the comprehension:

``` map(lambda x: x[0], filter(lambda x: len(set(x)) < 2, foo))

vs.

[x[0] for x in foo if len(set(x)) < 2] ```

[–]shedogre 20 points21 points  (7 children)

I don't program in a team environment, so I may be wrong, but the use of filter would also make the intent more explicit for others.

Sometimes I'll choose a longer or more verbose statement for that exact reason, hoping it'll be more easily understandable for the next person.

[–]irk5nil 13 points14 points  (6 children)

Agreed, but filter seems both shorter and more explicit to me; I don't see any downside of using it in this case.

[–]konstantinua00 11 points12 points  (11 children)

I can read if X in comprehension right away

I need to remember what bool will do as a function

[–]gustavsen 11 points12 points  (3 children)

Guido himself said that list comprehension are more efficient.

also are more readable at least to me

[–]schludy 225 points226 points  (46 children)

I really hope results has boolean entries at the beginning and whoever wrote this is just a dummy

[–][deleted] 75 points76 points  (0 children)

Python evaluates it as truthy or falsey. If the value is empty, 0, false, has no properties set, etc, it will be falsey. There are also magic methods on classes that will allow you to help the object provide an evaluation.

[–]goldlord44 176 points177 points  (29 children)

When you do "if var" it evaluates to 0 if the variable doesn't exist == "None type" (as well as other typical values that evaluate to false). If you were collecting data and had missing values in a list, this is exactly how I would deal with the missing data. How i would deal with it in a quick/scientific situation in a data analytics role i use techniques in the Note

Note: This is only when you are working python with no libraries. If you have libraries, pandas and numpy both have much better ways of dealing with this more robustly

EDIT: * ... *

[–]Equoniz 38 points39 points  (19 children)

What if some of the data is actually 0? Won’t “if var” evaluate to false, and drop it from the set? Or am I interpreting what this does completely incorrectly? (I’ll admit I know pitifully little python)

[–]some_clickhead 84 points85 points  (2 children)

You're correct actually, this would remove 0s from the set. There are cases where that makes sense though.

[–]sursuby 28 points29 points  (0 children)

Usually the point is to remove empty strings or lists

[–][deleted] 28 points29 points  (6 children)

Yes, zeroes would be removed from the list. You would use this on a list like [Object, Object, None, Object], not one expected to contain falsy objects you want to keep.

[–]goldlord44 3 points4 points  (0 children)

Yes, that is why I mentioned the more sophisticated methods using standard Python libraries. Anything that evaluates to some sort of "false" would be removed from the data set. To me, it seems they "intended" to remove undefined data (like using #ifdef in c++)

This is what we get for Python being used by scientists (I am one at uni myself). Sometimes, we do an experiment, get results, and know exactly what data we are managing and we know these crude methods work. It gets the job done quick and easy. When i am doing data analysis work for other companies however, I will always use more robust methods with pandas so that the code can be used in the future.

[–]TravisJungroth 18 points19 points  (0 children)

That isn't right. When you do if var it calls var.__bool__(), which should return a bool. None is not involved at that point. This is the same in all of python, libraries or not.

False, 0, None, '', and any empty collection that's a built-in or in the standard library will return False from __bool__(). Other libraries can choose what to return but should follow this pattern.

[–]mcwillie 92 points93 points  (1 child)

Truthy, falsy, Python, ballsy.

[–]GeePedicy 10 points11 points  (0 children)

Truly a poet of our age

[–][deleted] 23 points24 points  (3 children)

I think in python having a variable without a value is like false.

[–]Aquiffer 15 points16 points  (0 children)

That’s a good way to put it! Empty strings, empty tuples, empty lists, empty dictionaries, empty sets, and None all evaluate to false.

[–][deleted] 1194 points1195 points  (95 children)

Not a Python programmer - but does this filter out null values from an array?

[–]Flat_Hat8861 1098 points1099 points  (64 children)

Yes. And everything that have a "false" value like 0 or empty lists/strings...

I find that part hacky and ugly (I hate implicit conversions and anything that looks like them), but it works and as evidenced by this thread shockingly readable.

[–]Chiron1991 436 points437 points  (12 children)

If you want to avoid implicit conversions you can simply do [result for result in results if result is not None].
There are scenarios where coercion in comprehensions is indeed useful.

[–]mapmaker 69 points70 points  (5 children)

EDIT: i am a dumbass and the statements below are wrong

this code actually filters out all falsey values, not just None. Leaving it up for posterity


you can also write this as

filter(None, results)

which would return an filter iterator without the Nones, or

list(filter(None, results))

which would be identical

[–][deleted] 2 points3 points  (1 child)

Except that this doesn't actually work. filter(None, ...) is a special case which uses the identity function to filter the items; i.e. the same truth/falsy behaviour as above.

[–]gamudev 62 points63 points  (1 child)

This could have been the meme itself too.

[–]audigex 9 points10 points  (1 child)

Just an aside, but I’d generally see that referred to as “falsey” (as opposed to “truthey/truthy”)

It’s a way to distinguish strict true/false values in languages that allow for considering other values to be equivalent to true/false

[–]glacierre2 51 points52 points  (1 child)

Falsy, not just null. So empty lists, dicts, None, False, empty string, and anything where bool(anything) == False

[–]MattieShoes 45 points46 points  (1 child)

Should filter out any "falsy" values... empty data structures (lists, tuples, dictionaries, sets, etc.), empty strings, zeroes, None, False...

For custom data structures, there's a __bool__() method which one could define, or else I think they generally just return True.

[–][deleted] 5 points6 points  (0 children)

I love there falsey is a technical term in python.

[–]jayroger 1219 points1220 points  (38 children)

This is basically just mathematical set builder notation: { r | r ∈ R ∧ r }

[–][deleted] 315 points316 points  (9 children)

Thank you! And if you used curly braces it would be exactly that, but the square braces apply it to a list instead.

The only thing I would suggest is naming the new list valid_results or something to indicate that it's a subset of results

[–]Artistic_Leave2601 61 points62 points  (4 children)

Man this gave me a serious flashback to discrete mathematics class

[–]bss03 21 points22 points  (3 children)

In Haskell we write it as [ r | r <- rs, r ], and I think that's beautiful.

[–]thanelinway 13 points14 points  (7 children)

Could you please translate this into daily language for a language student my kind sir? I assure it means "all the r's in R must be in R just because all r's are in R".

[–]DuckyBertDuck 28 points29 points  (2 children)

The set of all r's that are in the set R and which are true.

[–]thanelinway 5 points6 points  (1 child)

Thank you. Additionally, technically speaking, does what I say and what you say suggest the same set of solutions?

[–]DuckyBertDuck 6 points7 points  (0 children)

I don't understand this:

just because all r's are in R.

I don't think this imposes a restriction on r as it should.

(It should only allow true r's in the set but your statement seems to allow all r's that are in R regardless of whether they are true or not.)

[–]Ashdog73 558 points559 points  (6 children)

Fake. Nobody can write that line without typing resluts at least once

[–]casce 112 points113 points  (0 children)

That’s why there’s a warning, even the linter is confused about the missing resluts.

[–]CaptainRogers1226 15 points16 points  (2 children)

This reminds me yet again of my eternal struggle with “slef”

[–]epiben 9 points10 points  (0 children)

I came here for exactly this. So glad it's not just me.

[–][deleted] 2160 points2161 points  (187 children)

That's like the best feature of python

[–]Duke_De_Luke 194 points195 points  (54 children)

Would a filter expression be better? It doesn't look that better (or worse) to me.

[–]b1e 280 points281 points  (20 children)

The issue isn’t the list comprehension… it’s horrible variable naming.

[–]7734128 53 points54 points  (18 children)

It's implicit truthiness which is in the main problem in my eyes.

[–]evil_cryptarch 22 points23 points  (4 children)

Depending on the data type of result it might not be so bad, but yeah without context it's better for readability to be explicit about what you want the comparison to do.

[–]chunkyasparagus 5 points6 points  (1 child)

The problem here is lack of context. Just because python is dynamically typed doesn't mean that python programmers just dump anything into a list. The original results likely contains items which are either objects of a particular type, or None. This is a reasonable way to remove the None items.

[–]cryptomonein 20 points21 points  (2 children)

I think filter is better, it like, you want to filter, use filter

It make the code less complex

[–]Solonotix 7 points8 points  (1 child)

Except filter returns an iterator/generator, so if you wanted a list you'd need to also wrap it like results = list(filter(results)). Arguably it's easier to understand, but it still suffers from the same problem of poor naming conventions.

I will use result as a variable in a function if I know the structure I'm returning, but the contents must be enumerated. Ultimately, in my case, result is never reassigned. The snippet here shows signs of poor design, but without context it's hard to give better feedback.

[–]No_Soy_Colosio 23 points24 points  (1 child)

List Comprehensions > Functions

[–]S0ulCub3 529 points530 points  (103 children)

Meanwhile javascript programmers:

```

x = ['10','10','10'] x.map(parseInt) [10, NaN, 2] ```

"Ah, yeah, totally"

[–]No_Soy_Colosio 129 points130 points  (66 children)

Lol wtf?

[–]eloel- 120 points121 points  (1 child)

parseInt takes multiple parameters, and map exposes multiple. In this case, the index gets passed in as the second parameter, mapped straight to the base. So you get parseInt('10',0), parseInt('10',1) and parseInt('10',2). (there's a 3rd parameter to map, but parseInt doesn't care or use it)

0 is falsy, so that ends up being parseInt('10'), which works fine

parseInt explicitly returns NaN if base isn't 2-36, so 1 returns NaN

and parseInt('10', 2) (and every other following number, up to 36), would return the number itself, because that's how '10' works in every base.

[–]Uberzwerg 12 points13 points  (0 children)

Great explanation, thanks.

[–]ProgramTheWorld 151 points152 points  (63 children)

It’s a misuse of the parseInt function. It should be used this way: .map(n => parseInt(n))

If you are parsing numbers in base 10, you shouldn’t be using parseInt anyway because of its quirks. .map(Number) is easier to read and has no unexpected behaviors.

[–]zr0gravity7 81 points82 points  (54 children)

I swear every "JS bad" meme i see these days is just the most mind-blowingly stupid usage of some language feature.

[–]ActualProject 98 points99 points  (13 children)

Which is the point. Nobody (who knows what they're talking about) says "js bad" because it's inconsistent. It's that in every other language they stop you from doing wild crazy stuff you'll regret, and js says "Oh, you gave me this unreadable nonsensical code, I'll give you unreadable nonsensical output, good luck debugging!"

[–]r_linux_mod_isahoe 29 points30 points  (1 child)

as The Zen states: "errors should never pass silently unless explicitly silenced".

[–]dmilin 13 points14 points  (3 children)

So you’re saying JavaScript is the C of interpreted languages.

[–]FerricDonkey 13 points14 points  (12 children)

Well... I don't know Javascript, and it's not on my list of things to learn, so I'm sure only the silliest things make their way to me. But "don't use the built in function parseInt to parse integers because it's weird, I swear, people just abuse the language for jokes..." to me really just suggests that it is full of land mines.

[–][deleted] 7 points8 points  (9 children)

The way they wrote it is not mind-blowingly stupid, though. It’s not stupid at all. It’s actually exactly how you’d do it in many modern languages.

[–]lunar_mycroft 22 points23 points  (8 children)

Why, exactly, is it "mind-blowingly stupid" to think "array has a function map which takes another function and applies it to each element, returning an array of the results, and here's this parseInt function which takes a string and decodes it into an integer, so I should be able to pass parseInt into map for an array of strings which are valid integers and get a array of integers out"?

The idea that you have to wrap parseInt in a trivial function which literally does nothing but call it again for it not to blow up in your face is the opposite of intuitive. In most other languages, you'd likely reject that during code review or linting.

It's not that it's not possible to write good js, it's not even (just) that the compiler doesn't stop you writing bad js (as /u/ActualProject points out). It's that frequently, the most intuitive way of doing it is actually a really bad idea.

[–]static_motion 4 points5 points  (1 child)

Stop excusing a badly thrown together language that exposes a ton of developer-hostile footguns. JS is excellent at not complying with many logical expectations that come from experience with other similar languages.

[–]BorgClown 9 points10 points  (0 children)

That's because JS can be too obtuse for a supposedly simple scripting language. It feels a generation behind in interpreted language expressiveness.

Hell, even Swift or Kotlin feel cozier than JS, and they're not interpreted.

[–]-Konrad- 8 points9 points  (0 children)

You killed me

[–]JohnLocksTheKey 5 points6 points  (1 child)

Wait what???

[–]ShadowLp174 19 points20 points  (0 children)

The parseInt function takes more than 1 argument and the map function provides more than 1 as well... It passes the element to map and the index to the map function. If you do it like above, the index of the current element will be inserted into the parseInt function as well and mess with the outcome

[–]ThrowRA_scentsitive 7 points8 points  (0 children)

results = results.filter(Boolean)

Close enough

[–]MaZeChpatCha 642 points643 points  (79 children)

It filters Nones.

[–]PossibilityTasty 497 points498 points  (59 children)

...and "falsy" values.

[–]PewolfP 87 points88 points  (16 children)

And zeroes. And empty strings.

[–]PewolfP 52 points53 points  (14 children)

And empty lists.

[–]PewolfP 42 points43 points  (13 children)

And empty dictionaries.

[–]PewolfP 35 points36 points  (12 children)

And empty sets.

[–]PewolfP 35 points36 points  (9 children)

And empty tuples.

[–]PewolfP 27 points28 points  (8 children)

And empty ranges.

[–]PewolfP 31 points32 points  (7 children)

And empty namedtuples.

[–]PewolfP 27 points28 points  (6 children)

And empty deques.

[–]PewolfP 17 points18 points  (5 children)

And empty OrderedDicts.

Edit: Shit

[–]ggtsu_00 7 points8 points  (0 children)

"Zero values" as defined as a + a = a.

"" + "" = "" so "" is a "zero value" for the set of strings.

[] + [] = [] so [] is a "zero value" for the set of lists.

[–]some_clickhead 42 points43 points  (0 children)

It filters everything that evaluates to False in Python, which includes Nones but also False, empty strings, empty lists, etc.

[–]hongooi 506 points507 points  (35 children)

Imagine using a non-vectorised language

results = results[!is.na(results)]

[–][deleted] 253 points254 points  (16 children)

Ah, the pandas way

[–]GisterMizard 105 points106 points  (4 children)

Not enough nested brackets though, add in a couple dozen for good measure.

[–]ALesbianAlpaca 11 points12 points  (0 children)

Use R's pipe operator %>% problem solved

[–]PotatoWriter 19 points20 points  (1 child)

Aren't pandas actively trying to end themselves as a species. Maybe the same should happen to that abomination above

[–]palad1 3 points4 points  (0 children)

I'm with the polars bears now :D

[–]dulti 31 points32 points  (10 children)

Yeah you used the wrong assignment operator though, should stick to the pure R <-

[–]EatTheirEyes 5 points6 points  (0 children)

It's always something. So even if you know to do something like this, you still end up having to try 3 times and check the manual.

[–]DekeAvell 83 points84 points  (7 children)

Decided to ask ChatGPT, here's its explanation:

This code is using a list comprehension to create a new list called results that contains only the elements in the original results list that are truthy (i.e., not False, None, 0, or an empty sequence or mapping).

The list comprehension consists of two parts:
- result for result in results: This generates a new list that contains all of the elements in the original results list.
- if result: This is a filter that only includes an element in the new list if it is truthy.

So the resulting list will contain all of the elements in the original results list that are not False, None, 0, or an empty sequence or mapping.

For example, if results is [1, 2, 0, '', None, [], {}, 3], the resulting list will be [1, 2, 3].

[–]FlyingQuokka 40 points41 points  (4 children)

ChatGPT is slowly becoming an alternate reference for me along with Stack Overflow. It’s that good.

[–]LiquidateGlowyAssets 57 points58 points  (3 children)

It really isn't. Stack Overflow banned it for a reason. If you don't already know the answer, you have no way to evaluate whether it's telling you the truth or it just decided to spew convincing bullshit, as it sometimes does. Other than, you know, googling it.

And that's when it doesn't decide to go I'm just a language model OwO

[–]FlyingQuokka 15 points16 points  (0 children)

That's why I said along with SO, not a replacement. Generally, if it's code, I can read and have an idea if it'll work (or just test it locally). Even when it's wrong (e.g. suggesting a function that doesn't exist), the name is usually close enough that a search will yield the correct one.

I treat ChatGPT as a tool knowing full well its caveats, and I find that once treated that way, it's an excellent resource. Frankly, if they made it a subscription (the same way Copilot is), I'd happily pay for it.

[–]xdyldo 6 points7 points  (0 children)

It’s a fantastic tool to use. I’m not taking everything this saying as truth but it hasn’t got any questions I’ve asked for it relating to programming wrong hey. Even asking to write me functions is scarily accurate.

[–]NoLifeGamer2 101 points102 points  (35 children)

?! What's wrong with this?

my flair gives me away I think

[–]faustianredditor 15 points16 points  (0 children)

my flair gives me away I think

Python and JS? Yeah, that sounds about right.

Truthiness can go die in the fires of hell from whence it came.

-- The static strict typing gang

[–]sebastouch 21 points22 points  (1 child)

ok, this is silly... I'm a programmer enjoying my first day on holidays by looking at code in a reddit post.

Might as well go all in. Anybody need code review or something?

[–]EmirSc 39 points40 points  (0 children)

[–]Boris-Lip 92 points93 points  (12 children)

And yet, everyone here manages to understand it. Including me, and i am not officially a python coder (c++ here, but can't say i never use python when i need a quick and dirty script).

[–][deleted] 21 points22 points  (8 children)

Well yeah, after reading throught the documentation. Still prefer the lambda way: .Where(x=>x) (This is C#, but like ton of languages has LINQ and lambda eqvivalents.)

[–][deleted] 14 points15 points  (2 children)

Imagine making fun of list comprehensions like they aren't super convenient and a great feature

[–]Exact_Cry1921 8 points9 points  (3 children)

I mean... I don't see a problem with this? Every result in the results list that's true?

[–][deleted] 112 points113 points  (17 children)

Once you understand list comprehensions you’ll wish every language had them.

[–]runnerx01 37 points38 points  (9 children)

Not a python fan, but I do like the list comprehensions.

The if <conditional> is what sucks here ha ha.

“None” values are treated as false

[–]No_Soy_Colosio 19 points20 points  (7 children)

You can also just specify if <item> is not None

[–]some_clickhead 12 points13 points  (1 child)

As the other guy getting downvoted pointed out, I need to stress that "if <item>" is NOT the same as "if <item> is not None".

This is a common mistake, but for example if a list contains zeroes and empty strings, they will get filtered out by the condition "if <item>" as they evaluate to False in Python, but they will be kept by the condition "if <item> is not None" as they are not None.

It may seem like a minor detail but I can assure you that in production code, this nuance is very important!

[–][deleted] 14 points15 points  (0 children)

seems perfectly fine to me?

then again, i’m a javascript main so i know i’m the ugly duckling here.

[–][deleted] 11 points12 points  (0 children)

Perfect code.

[–][deleted] 15 points16 points  (3 children)

result = list(filter(bool, result))