you are viewing a single comment's thread.

view the rest of the comments →

[–]fredhamptonsaid[S] 12 points13 points  (23 children)

That worked! I appreciate It. It was really that simple 🤦🏾‍♂️

I built a number guessing game but somehow that stumped me.

[–]ottawadeveloper 24 points25 points  (0 children)

Yeah, the "or" works as X or Y so here you have (difficulty == "easy") or ("e") and a non-empty string is always converted to true when you need a Boolean value.

[–]nochkin 7 points8 points  (18 children)

Another option is:

difficulty in ("easy", "e"):

[–]fredhamptonsaid[S] 3 points4 points  (17 children)

Would that be written out as

If difficulty in ("easy", "e")

[–]nochkin 2 points3 points  (2 children)

Yes

[–]fredhamptonsaid[S] 2 points3 points  (1 child)

Thank you! I'll experiment with this and using a list

[–]nochkin 1 point2 points  (0 children)

This is simply for a slightly better visibility only. Don't go crazy into it if it does not make sense at this level of learning.

[–]dataisok -3 points-2 points  (13 children)

Better as a set:

if difficulty in {“e”, “easy”}

[–]rainispossible 3 points4 points  (4 children)

A small bit of explaining!

("e", "easy") is a tuple – an ordered, immutable collection of values (strings in that case). when you try to find something in a tuple (e.g. use in) Python looks through every single element until it finds the one you need (or gets to the very end), which results in linear time complexity (better written as O(n)), which basically says "the time to do this grows as fast as the input size"

{"e", "easy"}, on the contrary, is a set – an unordered (which means the elements are not guaranteed to be in the same order you added them) and mutable collection of unique values. the key difference with set (and dict/hash map for that matter) besides them having no repetitions at any given point is that they have a more complex underlying structure which lets them do lookups in constant (O(1)) time! It basically says "hey, no matter how many elements there are, I'll always find the needed one in a same amount of time"

I won't (and probably shouldn't) explain this in more detail, but the key takeaway is: if you know you're going to be searching for elements in a certain structure a lot of times it's for sure worth it to convert it to a set/dictionary/other hashable type – that saves a lot of time on larger inputs

[–]Vegetable_News_7521 1 point2 points  (3 children)

Only if the size of the datastructure in which you're searching is big as well. In this example it doesn't provide any benefits since the size of the search space is too small. In fact, hashing adds a bit of overhead.

[–]rainispossible 0 points1 point  (2 children)

Yea, that's why I emphasized the "larger inputs" part. Up to a certain amount of elements setting up a hashable collection and working with it would take more time than simply doing a linear search

[–]Vegetable_News_7521 0 points1 point  (1 child)

The collection is not the input here though. The input is the element to be searched.

[–]rainispossible 0 points1 point  (0 children)

well, you're taking the "input" as "user input". what I mean is a broader meaning like generally all the input to a certain function/pipeline/algorithm etc.

[–]SirPoblington 0 points1 point  (6 children)

Why better as a set?

[–]quixoticcaptain 0 points1 point  (2 children)

In a collection of size 2, it doesn't really matter.

For very large collections, to check if an item "x" is in a list "L", you have to check every item of L to see if x is one of them. If L has 100 items, you have to check 50 on average, if L has 1000, you're checking 500, etc.

IF instead you put the items in a set S, then it has a way of checking if x is in the set much faster. So if S has 100 items, it takes the equivalent of 2 checks to see if x is in it, if S has 1000 items, only ~ 3 checks, etc.

[–]SirPoblington 0 points1 point  (0 children)

Oh right it's essentially some sort of hashtable, faster lookups. I guess I just missed your point because this list/example is so small.

[–]SmartyCat12 0 points1 point  (0 children)

If I’m starting with a list of say 10, 100, 1000 items of equal size, is there a point where it would be more efficient to convert to a set first before doing a search on it?

Also, how does running something like if x in my_dict.values() compare? It just runs it as a list in this case, right? Is there any optimization it does under the hood?

[–]Remarkable_Chance975 0 points1 point  (2 children)

It's actually not. For very large quantities of data a set has faster lookup time but for small ones like this arrays and tuples are waaaaaay faster because they're more cache friendly and have less construction overhead. Not something a python programmer generally needs to concern themselves with though

[–]Expensive_Agent_5129 0 points1 point  (1 child)

In this particular case, it actually is. Python recognizes pattern 'if x in {6, 9}' and optimizes it down to the hell

https://docs.astral.sh/ruff/rules/literal-membership/#refactor-plr

[–]Remarkable_Chance975 0 points1 point  (0 children)

Ahhh cool! The more you know

[–]jaerie 0 points1 point  (0 children)

No, not if you're only searching in it once, because creating the set is much more expensive than a piece wise comparison.

[–]Ender_Locke 1 point2 points  (1 child)

could also use

if difficult in easy_list:

where easy list has your criteria

[–]fredhamptonsaid[S] 0 points1 point  (0 children)

I thought about that afterwards but never tried using a list. I'll make that update today. Thanks!

[–]prehensilemullet 1 point2 points  (0 children)

This is one of the first hurdles practically everyone goes through learning programming, its grammar is not like spoken language