Mapping a list into a reference list - python

I am trying to make this as clear as I can. Please let me know if I should clarify anything.
I have a long list of variables in a list in the following format -
L = ["Fruit", "Transportation", "Housing", "Food", "Education"]
I would like to map a shorter list into it. The shorter list does not have each but only some of the variables in the long list. For instance -
S = ["Fruit", "Food"]
What I am interested in obtaining is the binary values of the short list while it maps into the L list.
With S as an example, it should be:
S = [1, 0, 0, 1, 0]
I tried map(S, L) but clearly a list is not callable.
TypeError: 'list' object is not callable
What would be a good way to do this? Thank you!!

By using a list comprehension that takes every value in L and if it is contained inside S it returns a value of 1, and, if not, it returns a value of 0:
m = [1 if subval in S else 0 for subval in L]
the result is:
[1, 0, 0, 1, 0]

Try this:
[int(x in S) for x in L]

You can use python's list comprehension as follow:
ans=[1 if x in S else 0 for x in L]

I tried map(S, L) but clearly a list is not callable.
But its methods are:
>>> map(S.count, L)
[1, 0, 0, 1, 0]
(This one assumes there are no duplicates in S. If that's not the case, you could for example use map(list(set(S)).count, L) instead.)

Related

List of strings to array of integers

From a list of strings, like this one:
example_list = ['010','101']
I need to get an array of integers, where each row is each one of the strings, being each character in one column, like this one:
example_array = np.array([[0,1,0],[1,0,1]])
I have tried with this code, but it isn't working:
example_array = np.empty([2,3],dtype=int)
i = 0 ; j = 0
for string in example_list:
for bit in string:
example_array[i,j] = int(bit)
j+=1
i+=1
Can anyone help me? I am using Python 3.6.
Thank you in advance for your help!
If all strings are the same length (this is crucial to building a contiguous array), then use view to efficiently separate the characters.
r = np.array(example_list)
r = r.view('<U1').reshape(*r.shape, -1).astype(int)
print(r)
array([[0, 1, 0],
[1, 0, 1]])
You could also go the list comprehension route.
r = np.array([[*map(int, list(l))] for l in example_list])
print(r)
array([[0, 1, 0],
[1, 0, 1]])
The simplest way is to use a list comprehension because it automatically generates the output list for you, which can be easily converted to a numpy array. You could do this using multiple for loops, but then you are stuck creating your list, sub lists, and appending to them. While not difficult, the code looks more elegant with list comprehensions.
Try this:
newList = np.array([[int(b) for b in a] for a in example_list])
newList now looks like this:
>>> newList
... [[0, 1, 0], [1, 0, 1]]
Note: there is not need to invoke map at this point, though that certainly works.
So what is going on here? We are iterating through your original list of strings (example_list) item-by-item, then iterating through each character within the current item. Functionally, this is equivalent to...
newList = []
for a in example_list:
tmpList = []
for b in a:
tmpList.append(int(b))
newList.append(tmpList)
newList = np.array(newList)
Personally, I find the multiple for loops to be easier to understand for beginners. However, once you grasp the list comprehensions you probably won't want to go back.
You could do this with map:
example_array = map(lambda x: map(lambda y: int(y), list(x)), example_list)
The outer lambda performs a list(x) operation on each item in example_list. For example, '010' => ['0','1','0']. The inner lambda converts the individual characters (resultants from list(x)) to integers. For example, ['0','1','0'] => [0,1,0].

How do I merge a value and a range or list in python in a single line?

I am quite new to python, and still learning simple data handling in python.
I would like to combine 1 and range(3) to get a list [1,0,1,2]. What is best way to do this?
Is there any easy way like [1,0:3]?
Extended iterable unpacking, Python3.6+
>>> [1, *range(3)]
[1, 0, 1, 2]
With numpy, there's an even more convenient/concise expression using np.r_:
>>> import numpy as np
>>> np.r_[1,0:3]
array([1, 0, 1, 2])
This seems to be the most concise:
[1] + list(range(3))
# The following code should introduce you to lists, variables, for loops and the
basic interaction amongst all of them.
# Assign variable rng the upper limit of your range.The upper limit is not considered
in Python ranges of any kind
# hence the number should be one more than the number you want to consider/use.
rng = 3
# Initialize an empty list for use later.
lst = []
# Assign variable num the value you want to add and append it to the list
num = 1
lst.append(num)
# Print the current list.
print(lst)
# Use a simple for loop to iteratively add numbers in your range to the list.
for i in range (0,rng):
lst.append(i)
# Print the updated list.
print(lst)
#Output :
[1]
[1, 0, 1, 2]
you could just count from -1 and forget all about the minueses with the absolute value
[abs(i) for i in range(-1,3)]
output
[1, 0, 1, 2]
OR a genrator
map(abs,range(-1,3))
output
<map object at 0x0000026868B46278>
this is the same as the first output just as a genrator
AS A LIST
list(map(abs,range(-1,3)))
output
[1, 0, 1, 2]

get list if contains non zero element

I have a list.
l1 = [0, 0, 2, 0]
l2 = [0, 0, 0, 0]
I want to print list if list contains non zero element in it.
Output:
If one one list passed, then only list with non zero element will get printed. In example above only l1 will get printed.
[0, 0, 2, 0]
I want to know how efficiently it can be done. Thanks !
Use any on your lists:
for lst in (l1, l2):
if any(lst):
print(lst)
You can also use all:
for lst in (l1, l2):
if all(x != 0 for x in lst):
print(lst)
I hope this helps.
You can use the built-in function any():
From Python's documentation:
any(iterable)
Return True if any element of the iterable is true. If
the iterable is empty, return False
Here's a code:
for l in [l1,l2, ..., ln]:
if any(l):
print(l)
You can try this:
lists = [[0, 0, 0, 0],[0, 0, 2, 0]]
for l in lists:
if set(l)=={0}:
pass
else:
print l
You can use the built-in any to test if the list contains at least one non-Falsy/non-zero element.
Zero is falsy, in fact the only falsy number:
>>> bool(0)
False
So you can easily do:
for lst in (l1, l2):
if any(lst):
print(lst)
This would provide correct results as long as your lists contains only numericals and you're not willing to make an expcetion of non numericals.
Answered in the comments, but I'll post it as an answer:
for l in filter(any, (l1, l2)):
print(l)
The combination of filter and any makes it so the print only executes for lists with non-zero elements. any returns False as soon as the first non-zero (or truthy) value is encountered. For integers, 0 is the only i for which bool(i) is falsey.

How to check if a sequence of INTs are in a list and remove them in Python

I have a list with integers, in which every second int is zero (0), like this:
mylist = [1,0,2,0,3,0,4,0]
I can only check single positions like so:
for i in range(0, len(mylist)):
if i in mylist:
#do something here
I am trying to check for two positions at every loop, so if the loop finds for example "2, 0" in mylist, it will be able to remove those two ints.
Any suggestion will be appreciated.
Since the values between the 0s are unique, you can simply use list.index to find the target value and then use del to delete this value and the next one from the list:
>>> my_list = [1,0,2,0,3,0,4,0]
>>> my_index = my_list.index(3)
>>> del my_list[my_index:my_index+2]
>>> my_list
[1, 0, 2, 0, 4, 0]
Here is an example if you wanna remove the sequence (2,0), taking into account flatten method mentionned below:
from itertools import izip, chain
>>> list(chain(*[[u,v] for u,v in izip(*[iter(mylist)]*2) if (u,v)!=(2,0)]))
[1, 0, 3, 0, 4, 0]
All credits goes to:
Creating a python dictionary from a line of text

How to replace values at specific indexes of a python list?

If I have a list:
to_modify = [5,4,3,2,1,0]
And then declare two other lists:
indexes = [0,1,3,5]
replacements = [0,0,0,0]
How can I take to_modify's elements as index to indexes, then set corresponding elements in to_modify to replacements, i.e. after running, indexes should be [0,0,3,0,1,0].
Apparently, I can do this through a for loop:
for ind in to_modify:
indexes[to_modify[ind]] = replacements[ind]
But is there other way to do this?
Could I use operator.itemgetter somehow?
The biggest problem with your code is that it's unreadable. Python code rule number one, if it's not readable, no one's gonna look at it for long enough to get any useful information out of it. Always use descriptive variable names. Almost didn't catch the bug in your code, let's see it again with good names, slow-motion replay style:
to_modify = [5,4,3,2,1,0]
indexes = [0,1,3,5]
replacements = [0,0,0,0]
for index in indexes:
to_modify[indexes[index]] = replacements[index]
# to_modify[indexes[index]]
# indexes[index]
# Yo dawg, I heard you liked indexes, so I put an index inside your indexes
# so you can go out of bounds while you go out of bounds.
As is obvious when you use descriptive variable names, you're indexing the list of indexes with values from itself, which doesn't make sense in this case.
Also when iterating through 2 lists in parallel I like to use the zip function (or izip if you're worried about memory consumption, but I'm not one of those iteration purists). So try this instead.
for (index, replacement) in zip(indexes, replacements):
to_modify[index] = replacement
If your problem is only working with lists of numbers then I'd say that #steabert has the answer you were looking for with that numpy stuff. However you can't use sequences or other variable-sized data types as elements of numpy arrays, so if your variable to_modify has anything like that in it, you're probably best off doing it with a for loop.
numpy has arrays that allow you to use other lists/arrays as indices:
import numpy
S=numpy.array(s)
S[a]=m
Why not just:
map(s.__setitem__, a, m)
You can use operator.setitem.
from operator import setitem
a = [5, 4, 3, 2, 1, 0]
ell = [0, 1, 3, 5]
m = [0, 0, 0, 0]
for b, c in zip(ell, m):
setitem(a, b, c)
>>> a
[0, 0, 3, 0, 1, 0]
Is it any more readable or efficient than your solution? I am not sure!
A little slower, but readable I think:
>>> s, l, m
([5, 4, 3, 2, 1, 0], [0, 1, 3, 5], [0, 0, 0, 0])
>>> d = dict(zip(l, m))
>>> d #dict is better then using two list i think
{0: 0, 1: 0, 3: 0, 5: 0}
>>> [d.get(i, j) for i, j in enumerate(s)]
[0, 0, 3, 0, 1, 0]
for index in a:
This will cause index to take on the values of the elements of a, so using them as indices is not what you want. In Python, we iterate over a container by actually iterating over it.
"But wait", you say, "For each of those elements of a, I need to work with the corresponding element of m. How am I supposed to do that without indices?"
Simple. We transform a and m into a list of pairs (element from a, element from m), and iterate over the pairs. Which is easy to do - just use the built-in library function zip, as follows:
for a_element, m_element in zip(a, m):
s[a_element] = m_element
To make it work the way you were trying to do it, you would have to get a list of indices to iterate over. This is doable: we can use range(len(a)) for example. But don't do that! That's not how we do things in Python. Actually directly iterating over what you want to iterate over is a beautiful, mind-liberating idea.
what about operator.itemgetter
Not really relevant here. The purpose of operator.itemgetter is to turn the act of indexing into something, into a function-like thing (what we call "a callable"), so that it can be used as a callback (for example, a 'key' for sorting or min/max operations). If we used it here, we'd have to re-call it every time through the loop to create a new itemgetter, just so that we could immediately use it once and throw it away. In context, that's just busy-work.
You can solve it using dictionary
to_modify = [5,4,3,2,1,0]
indexes = [0,1,3,5]
replacements = [0,0,0,0]
dic = {}
for i in range(len(indexes)):
dic[indexes[i]]=replacements[i]
print(dic)
for index, item in enumerate(to_modify):
for i in indexes:
to_modify[i]=dic[i]
print(to_modify)
The output will be
{0: 0, 1: 0, 3: 0, 5: 0}
[0, 0, 3, 0, 1, 0]
elif menu.lower() == "edit":
print ("Your games are: "+str (games))
remove = input("Which one do you want to edit: ")
add = input("What do you want to change it to: ")
for i in range(len(games)) :
if str(games[i]) == str(remove) :
games[i] = str(add)
break
else :
pass
pass
why not use it like this? replace directly from where it was removed and anyway you can add arrays and the do .sort the .reverse if needed

Categories