Get a list of values from a list of enumerations - python

Let us assume that we have an enum class:
class MyEnum(Enum):
foo = 1
bar = 2
How to get the list of values [1, 1, 2] from the above list of enumerations?
mylist = [MyEnum.foo, MyEnum.foo, MyEnum.bar]
I know it is possible to create a new list using list comprehension, but I am wondering if there exists a more natural and straighforward way to get the same output.

we can access name and value of an Enum class by .name, .value. So a simple list comprehension could solve your problem.
class MyEnum(Enum):
foo = 1
bar = 2
mylist = [MyEnum.foo, MyEnum.foo, MyEnum.bar]
my_enum_val_list = [i.value for i in mylist]
Further, you can also use IntEnum to make it behaves just like a simple int array.
class MyEnum(IntEnum):
foo = 1
bar = 2
mylist = [MyEnum.foo, MyEnum.foo, MyEnum.bar]

I could only think about a map:
myvaluelist = list(map(lambda _ : _.value, mylist))
however I think it is much less 'natural' than list comprehesion:
myvaluelist = [_.value for _ in mylist]
[EDIT]
Also comprehesions are quite well optimized, which may be another plus, once one is used to them.

Let's try this:
nb_foo=2
nb_bar=1
mylist1=[MyEnum.foo for i in range(nb_foo)]
mylist2=[MyEnum.bar for i in range(nb_bar)]
mylist = mylist1 + mylist2
print(mylist)
Output
[1, 1, 2]

Related

Is there any Hashable list datatype? [duplicate]

In Java we have HashSet<Integer>, I need similar structure in Python to use contains like below:
A = [1, 2, 3]
S = set()
S.add(2)
for x in A:
if S.contains(x):
print "Example"
Could you please help?
Just use a set:
>>> l = set()
>>> l.add(1)
>>> l.add(2)
>>> 1 in l
True
>>> 34 in l
False
The same works for lists:
>>> ll = [1,2,3]
>>> 2 in ll
True
>>> 23 in ll
False
Edit:
Note #bholagabbar's comment below that the time complexity for in checks in lists and tuples is O(n) on average (see the python docs here), whereas for sets it is on average O(1) (worst case also O(n), but is very uncommon and might only happen if __hash__ is implemented poorly).
In Python, there is a built-in type, set.
The major difference from the hashmap in Java is that the Python set is not typed,
i.e., it is legal to have a set {'2', 2} in Python.
Out of the box, the class set does not have a contains() method implemented.
We typically use the Python keyword in to do what you want, i.e.,
A = [1, 2, 3]
S = set()
S.add(2)
for x in A:
if x in S:
print("Example")
If that does not work for you, you can invoke the special method __contains__(), which is NOT encouraged.
A = [1, 2, 3]
S = set()
S.add(2)
for x in A:
if S.__contains__(x):
print("Example")

simple change of lists in python: efficient way?

if i have a list in python were i have a lot of numers example:
list = [1,2,3,12,4,5,23,5,6,56,8,57,8678,345,234,13, .....]
so a list of all integers, that all can have different values ... (i my case this list could be very long, and is actually not an integer list, but a list of Objects which are all from the same type an have a attribute age which is a integer)
whats the most efficient way to add all those values by +1
is it
new_list = [x+1 for x in list]
or maybe
new_list = []
for x in list:
new_list.append(x+1)
(i guess it makes no difference)
or is there maby a more efficent way or an other data sructure to make this more performant?
I really wonder if there is not any method, maybe using something different the a list were i can do this operation more efficient because the +1 seems son simple ...
If you actually have a list of objects with an integer attribute, as you say, you can update the attribute in-place:
class A(object):
def __init__(self, x):
self.x = x
my_list = [A(2), A(5), A(1)]
for obj in my_list:
obj.x += 1
assert my_list[0].x == 3
assert my_list[1].x == 6
assert my_list[2].x == 2
There is no fastest way but I think this is an interesting attempt since u never use more RAM than actually needed (u delete the entries once you copied them)
list1 = []
while (len(list) != 0):
list1.append(list.pop(0)+1)
After receiving a comment I did some testing and found the results very interesting!
Try to use map. It must be fast due to some built-in optimizations.
t = [1, 2, 3, 4, 5, 6, 7, 8]
print (map(lambda x:x + 1, t))

Copy values from one list to another without altering the reference in python

In python objects such as lists are passed by reference. Assignment with the = operator assigns by reference. So this function:
def modify_list(A):
A = [1,2,3,4]
Takes a reference to list and labels it A, but then sets the local variable A to a new reference; the list passed by the calling scope is not modified.
test = []
modify_list(test)
print(test)
prints []
However I could do this:
def modify_list(A):
A += [1,2,3,4]
test = []
modify_list(test)
print(test)
Prints [1,2,3,4]
How can I assign a list passed by reference to contain the values of another list? What I am looking for is something functionally equivelant to the following, but simpler:
def modify_list(A):
list_values = [1,2,3,4]
for i in range(min(len(A), len(list_values))):
A[i] = list_values[i]
for i in range(len(list_values), len(A)):
del A[i]
for i in range(len(A), len(list_values)):
A += [list_values[i]]
And yes, I know that this is not a good way to do <whatever I want to do>, I am just asking out of curiosity not necessity.
You can do a slice assignment:
>>> def mod_list(A, new_A):
... A[:]=new_A
...
>>> liA=[1,2,3]
>>> new=[3,4,5,6,7]
>>> mod_list(liA, new)
>>> liA
[3, 4, 5, 6, 7]
The simplest solution is to use:
def modify_list(A):
A[::] = [1, 2, 3, 4]
To overwrite the contents of a list with another list (or an arbitrary iterable), you can use the slice-assignment syntax:
A = B = [1,2,3]
A[:] = [4,5,6,7]
print(A) # [4,5,6,7]
print(A is B) # True
Slice assignment is implemented on most of the mutable built-in types. The above assignment is essentially the same the following:
A.__setitem__(slice(None, None, None), [4,5,6,7])
So the same magic function (__setitem__) is called when a regular item assignment happens, only that the item index is now a slice object, which represents the item range to be overwritten. Based on this example you can even support slice assignment in your own types.

Python - external variable being changed by function

I am trying to write a function that squares each value in a list, returning a new list with individual values squared. I pass a list to it and it changes the original list. I'd like it to not make any changes to the original list, so that I can use it in other functions.
def squareset(c):
d=c
count = len(c)
print(c)
for i in range(0,(count),1):
d[i]=d[i]**2
return d
test = [1,2,3]
print(squareset(test))
print(test)
I don't have this problem with functions operating on simple variables of type int or float.
I added the d=c line trying to prevent the change to the list test, but it makes no difference. print(test) is producing the result [1,4,9] instead of [1,2,3]. Why is this happening and how can I fix this?
Doing d=c simply makes the parameter d point to the same object that c is pointing to. Hence, every change made to d is made to the same object that c points to.
If you want to avoid changing c you'll have to either send a copy of the object, or make a copy of the object inside the function and use this copy.
For example, do:
d = [i for i in c]
or:
d = c[:]
instead of:
d = c
Assigning the list to another variable doesn't copy the list. To copy, just
def squareset(c):
d=c[:]
...
While the other answers provided are correct I would suggest using list comprehension to square your list.
In [4]:
test = [1,2,3]
results = [elm**2 for elm in test]
print test
print results
[1, 2, 3]
[1, 4, 9]
If you wanted a function:
def squareList(lst):
return [elm**2 for elm in lst]
Try this:
def square(var):
return [x*x for x in var]
x = [1,2,3]
z = square(x)

How to work with one List on few Classes without effects on that list

I'm comparing a few algorithms.Each algorithms(class) received the same list. The problem is that first class affect on list and other classes cannot work on that list.
Is there any clever way to do this?
Here is a code:
Lista = []
start = 54
for i in range(25):
liczba = random.randint(1,179)
if liczba not in Lista and liczba != start:
Lista.append(liczba)
else:
i -= 1
print "Lista: ", Lista
x = SSTF(Lista)
x.Symulacja(91) #<----- OK!
y = FCFS(Lista)
y.Symulacja(25) #<----- FCFS received epty list.
z = SCAN()
z.Symulacja(start, Lista)
w = C_SCAN()
w.Symulacja(start, Lista)
results = Result()
results.Add(x)
results.Add(y)
print Results
SSTF is removing elements from list which received, FCFS the same. So after doing SSTF algorithm FCFS reveived empty list. I can't understand why this list is affected. I'm not working on List "Lista", but in init of SSTF i'm assigning "Lista" to other list.
Sorry if my problem is not a clear. I'm learning python and that problem hits me many times.
x = SSTF(Lista[:])
y = FCFS(Lista[:])
....
etc...
Your problem:
def SSTF(Lista):
Listb = Lista
means that Listb is still the same Lista, because this is a reference to the same object.
To avoid it, copy the list entirely, using [:] slice notation (Python dictionaries have the .copy() method, which is clearer).
Basically, any time you copy a reference to an object from one variable to another variable, you are ending up with two pointers to the same object so changes to that object will be seen by both variable names. Yeah, sorry about the terminology.
The pointer is shown by the id() code below. Notice how li == li2 != li3
>>>li = [1,2]
>>>li2 = li
>>>li3 = li[:]
>>>li2.append(3)
>>>print "li:", id(li), li
>>>print "li2:", id(li2), li2
>>>print "li3:", id(li3), li3
li: 4385880760 [1, 2, 3]
li2: 4385880760 [1, 2, 3]
li3: 4385924376 [1, 2]
This is not the case with things like numbers or strings. Check out also the concept of 'immutable'.
>>> a = "xxx"
>>> b = a
>>> b = b +"y"
>>> print a, b
xxx xxxy
>>> a = 1
>>> b = a
>>> b =b+1
>>> print a, b
1 2
If you need to copy your custom classes' instances, look into the copy module, but keep in mind that instance attributes are either shared or copied, depending on using copy.copy(x) or copy.deepcopy(x). In practice, this is rarely necessary, but I got bitten many times by Lista type issues on built-in collection classes before I learned my lesson.

Categories