Generating a list using another list and an index list - python

Suppose I have the following two list and a smaller list of indices:
list1=[2,3,4,6,7]
list2=[0,0,0,0,0]
idx=[1,2]
I want to replace the values in list 2 using the values in list 1 at the specified indices.
I could do so using the following loop:
for i in idx:
list2[i]=list1[i]
If I just have list1 and idx , how could I write a list comprehension to generate list2 (same length as list1)such that list2 has values of list1 at indices idx or 0 otherwise.

This will call __contains__ on every call for idx but should be reasonable for small(ish) lists.
list2 = [list1[i] if i in idx else 0 for i in range(len(list1))]
or
list2 = [e if i in idx else 0 for i, e in enumerate(list1)]
Also, do not write code like this. It is much less readable than your example. Furthermore, numpy may give you the kind of syntax you desire without sacrificing readability or speed.
import numpy as np
...
arr1 = np.array(list1)
arr2 = np.zeros_like(list1)
arr2[idx] = arr1[idx]

I assume that you want to generate list2 by using appending values of list1 at specific indexes. All you need to do this is to check whether the idx list contains any values and then use a for each loop to append the specific list1 values to list2. If idx is empty then you would only append list1[0] to list2.
if(len(idx) > 0):
for i in idx:
list2.append(list1[i])
else:
list2.append(list1[0])

Related

List comprehension using index values

How do I turn the below for loop into a list comprehension?
I have a list of lists. Each sublist has a number in index 4 position, and I would like to find a way to add them up. The for loop works, but I'd like a one-line solution with list comprehension.
frequencies = []
for row in table:
frequencies.append(int(row[4]))
sum(frequencies)
Here's my attempt:
frequencies = [sum(i) for i, x in enumerate(table) if x == 4]
However, the result is an empty object.
In[52]: total
Out[52]: []
Do it like this -
frequencies = sum([int(row[4]) for row in table])
The approach you're using is a little different from what you want to achieve.

how to get a range of values from a list on python?

I'd like to do the following Matlab code:
indexes=find(data>0.5);
data2=data(indexes(1):indexes(length(indexes))+1);
in Python, so I did:
indexes=[x for x in data if x>0.5]
init=indexes[1]
print(indexes)
end=indexes[len(indexes)]+1
data2=data[init:end]
but I'm getting this error:
end=indexes[len(indexes)]+1 IndexError: list index out of range
I think the indexes in Python may not be the same ones as I get in Matlab?
Your list comprehension isn't building a list of indices, but a list of the items themselves. You should generate the indices alongside the items using enumerate:
ind = [i for i, x in enumerate(data) if x > 0.5]
And no need to be so verbose with slicing:
data2 = data[ind[0]: ind[-1]+1] # Matlab's index 1 is Python's index 0
Indexing the list of indices with len(ind) will give an IndexError as indexing in Python starts from 0 (unlike Matlab) and the last index should be fetched with ind[len(ind)-1] or simply ind[-1].
len(indexes) will give you the index of the last element of the list, so that value plus 1 is out of the range of the list.
It looks like what you're trying to do is find the indices of the list that have values of greater that 0.5 and put those values into data2. This is better suited to a numpy array.
import numpy as np
data2 = data[data > 0.5]

Find indexes of common items in two python lists

I have two lists in python list_A and list_B and I want to find the common item they share. My code to do so is the following:
both = []
for i in list_A:
for j in list_B:
if i == j:
both.append(i)
The list common in the end contains the common items. However, I want also to return the indexes of those elements in the initial two lists. How can I do so?
It is advised in python that you avoid as much as possible to use for loops if better methods are available. You can efficiently find the common elements in the two lists by using python set as follows
both = set(list_A).intersection(list_B)
Then you can find the indices using the build-in index method
indices_A = [list_A.index(x) for x in both]
indices_B = [list_B.index(x) for x in both]
Instead of iterating through the list, access elements by index:
both = []
for i in range(len(list_A)):
for j in range(len(list_B)):
if list_A[i] == list_B[j]:
both.append((i,j))
Here i and j will take integer values and you can check values in list_A and list_B by index.
You can also get common elements and their indexes with numpy.intersect1d()
common_elements, a_indexes, b_indexes = np.intersect1d(a, b, return_indices=True)

How to merge n lists together item by item for each list

I want to make one large list for entering into a database with values from 4 different lists. I want it to be like
[[list1[0], list2[0], list3[0], list4[0]], [list1[1], list2[1], list3[1], list4[1]], etc.....]
Another issue is that currently the data is received like this:
[ [ [list1[0], list1[1], [list1[3]]], [[list2[0]]], etc.....]
I've tried looping through each list using indexs and adding them to a new list based on those but it hasn't worked, I'm pretty sure it didn't work because some of the lists are different lengths (they're not meant to be but it's automated data so sometimes there's a mistake).
Anyone know what's the best way to go about this? Thanks.
First list can be constructed using zip function as follows (for 4 lists):
list1 = [1,2,3,4]
list2 = [5,6,7,8]
list3 = [9,10,11,12]
list4 = [13,14,15,16]
res = list(zip(list1,list2,list3,list4))
For arbitrtary number of lists stored in another list u can use *-notation to unpack outer list:
lists = [...]
res = list(zip(*lists))
To construct list of lists for zipping from you data in second issue use flatten concept to it and then zip:
def flatten(l):
res = []
for el in l:
if(isinstance(el, list)):
res += flatten(el)
else:
res.append(el)
return res
auto_data = [...]
res = list(zip(*[flatten(el) for el in auto_data]))
Some clarification at the end:
zip function construct results of the smallest length between all inputs, then you need to extend data in list comprehension in last code string to be one length to not lose some info.
So if I understand correctly, this is your input:
l = [[1.1,1.2,1.3,1.4],[2.1,2.2,2.3,2.4],[3.1,3.2,3.3,3.4],[4.1,4.2,4.3,4.4]]
and you would like to have this output
[[1.1,2.1,3.1,4.1],...]
If so, this could be done by using zip
zip(*l)
Make a for loop which only gives you the counter variable. Use that variable to index the lists. Make a temporary list , fill it up with the values from the other lists. Add that list to the final one. With this you will et the desired structure.
nestedlist = []
for counter in range(0,x):
temporarylist = []
temporarylist.append(firstlist[counter])
temporarylist.append(secondlist[counter])
temporarylist.append(thirdlist[counter])
temporarylist.append(fourthlist[counter])
nestedlist.append(temporarylist)
If all the 4 lists are the same length you can use this code to make it even nicer.
nestedlist = []
for counter in range(0,len(firstlist)): #changed line
temporarylist = []
temporarylist.append(firstlist[counter])
temporarylist.append(secondlist[counter])
temporarylist.append(thirdlist[counter])
temporarylist.append(fourthlist[counter])
nestedlist.append(temporarylist)
This comprehension should work, with a little help from zip:
mylist = [i for i in zip(list1, list2, list3, list4)]
But this assumes all the list are of the same length. If that's not the case (or you're not sure of that), you can "pad" them first, to be of same length.
def padlist(some_list, desired_length, pad_with):
while len(some_list) < desired_length:
some_list.append(pad_with)
return some_list
list_of_lists = [list1, list2, list3, list4]
maxlength = len(max(list_of_lists, key=len))
list_of_lists = [padlist(l, maxlength, 0) for l in list_of_lists]
And now do the above comprehension statement, works well in my testing of it
mylist = [i for i in zip(*list_of_lists)]
If the flatten concept doesn't work, try this out:
import numpy as np
myArray = np.array([[list1[0], list2[0], list3[0], list4[0]], [list1[1], list2[1], list3[1], list4[1]]])
np.hstack(myArray)
Also that one should work:
np.concatenate(myArray, axis=1)
Just for those who will search for the solution of this problem when lists are of the same length:
def flatten(lists):
results = []
for numbers in lists:
for output in numbers:
results.append(output)
return results
print(flatten(n))

Indices are not synchronous of using one lists indices in another

Coming from R, this was hard to grasp. Taking elements from a list start with position 0.
The problem is that using one list to select items from another list are not running at the same pace here.
list1 = [1,2,3,4]
list2 = [1,2,3,4]
for x in range(0, len(list1)):
print(list1[list2[x]])
This will result in:
>> 2
>> 3
>> 4
>> IndexError: list index out of range
When I put an extra item in the start of list1, and added an item at the end of list2, the problem stops (simply because they are not synchronous like this).
Obviously I am not familiar with the language yet, what would be the correct way to use values from one list to select values from another?
Is this the correct way to think of it?
for x in range(0, len(list1)):
print(list1[list2[x]-1])
Python is 0-index based. seq[0] is the first element in seq.
R is 1-index based.
So, yes, in python you could use
list1 = [1,2,3,4]
list2 = [1,2,3,4]
for x in range(0, len(list2)):
print(list1[list2[x]-1])
The range should go up to len(list2), not len(list1).
Also, range(0, len(list2)) is the same as range(len(list2)). When
range is passed only one argument, it is interpreted as the stop
value, with a start value of 0 taken by default.
Note that in Python
for x in range(...):
can often be avoided, and if so, is preferable. Instead, you can write
for item in list2:
print(list1[item-1])
and item will be assigned to each of the items in list2.
If your list has 4 items, your indexes must run from 0 to 3, so using the value 4 throws an error. Here's an example with letters which might make it clearer:
list1 = [0,2,1,3]
list2 = ['a','a','d','m']
for x in list1:
print(list2[x]),
=> a d a m

Categories