Related
I have a 2D list = [[1, 8, 3], [4, 5, 6], [0, 5, 7]], and I want to delete columns in a loop.
For example, columns with index: 0(first) and 2(last) - - the result after deletions should be: [8, 5, 5].
There is a problem, because when I delete the 0th column, the size of the list is decreased to (0,1), and the 2nd index is out of scope.
What is the fastest method to delete columns in a loop without the out-of-scope problem?
For a better picture:
[[1, 8, 3],
[4, 5, 6],
[0, 5, 7]]
There is no such shortcut in python except for iterating over all the list items and removing those index values.
However, you can use pandas which is meant for some other purpose but will do the task.
import pandas as pd
s = [[1, 8, 3], [4, 5, 6], [0, 5, 7]]
df = pd.DataFrame(s,columns=['val1','val2','val3'])
li = df.drop('val1',axis=1).values.tolist()
now li will look like this
[[8, 3], [5, 6], [5, 7]]
You can use numpy like this:
import numpy as np
my_list = np.array([[1, 8, 3], [4, 5, 6], [0, 5, 7]])
new_list = my_list[:, 1].copy()
print(new_list)
Output:
>>> [8, 5, 5]
Also numpy.delete(your_list, index, axis) is do the same job:
new_list = np.delete(my_list,(0, 2), axis=1)
(0, 2) is the indices of the columns 0 and 2
axis=1 says numpy that (0, 2) are columns indices not rows.
if you want to delete rows 0 and 2 you can change axis=1 to axis=0
Output is a little different:
>>> array([[8],
[5],
[5]])
For a pure python approach:
my_list = [[1, 8, 3], [4, 5, 6], [0, 5, 7]]
new_list = [value[1] for value in my_list]
print(new_list)
Output:
>>> [8, 5, 5]
L is 2D list:
print(map(lambda x: x[1:], L))
data= [[1, 8, 3], [4, 5, 6], [0, 5, 7]]
index_to_remove=[0,2]
[list(x) for x in zip(*[d for i,d in enumerate(zip(*data)) if i not in index_to_remove])]
If I understood your question correctly, you want to keep the middle element (index 1) of each list,in that case I would suggest creating a new list. There could be other better ways, for sure. But you could try this, if this works for you:
twoD_list = [[1, 8, 3], [4, 5, 6], [0, 5, 7]]
def keep_col( twoD_list ,index_to_keep = 1):
final_list = []
for x in twoD_list:
final_list.append(x[index_to_keep])
return final_list
final_list = keep_col( twoD_list , 1)
Final output:
[8,5,5]
Assuming you always want only the second element and the inner lists always have at least two elements.
Pure python with list comprehension:
lst = [
[1, 8, 3],
[4, 5, 6],
[0, 5, 7],
]
filtered_lst = [
inner_element
for inner_lst in lst
for i, inner_element in enumerate(inner_lst)
if i == 1
]
print(filtered_lst)
# [8, 5, 5]
If you want you can the reassign the new list to the old variable:
lst = filtered_lst
The advantages of this method are:
no need to worry about the list being altered while you iterate it,
no need to import other libraries
list comprehension is built-in
list comprehension is often the fastest way to filter a list (see for example this article)
easier to read and maintain that other solutions (in my opinion).
Via itemgetter to extract the value at index 1.
from operator import itemgetter
my_list = [[1, 8, 3], [4, 5, 6], [0, 5, 7]]
result = list(map(itemgetter(1), my_list))
try this
my_list = [[1, 8, 3], [4, 5, 6], [0, 5, 7]]
filter_col=[0,2]
col_length=3
my_list=[[x[i] for i in range(col_length) if i not in filter_col] for x in my_list]
u do not want to directly mutate the list that you are working on
this performs a list comprehension to create a new list from the existing list
edit:
just saw u wanted only a flat list
assuming u only want one element for the list u can use
my_list=[x[1] for x in my_list]
I have a dictionaries inside a list like this:
sample_dict = [{1: [[1, 2, 3, 4, 5, 6, 7, 8, 9, 10], \
[1, 2, 3, 4, 5], \
[1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11]]}, \
{2: [[3, 4, 6, 7, 8, 9, 10, 11], [1, 2, 3, 6, 10], []]}]
Now, I would like to check the key 1's first value in the list with key 2's first value.
something like this,
Compare Values (first value of list of lists of key 1)
[1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
with (first value of list of lists of key 2)
[3, 4, 6, 7, 8, 9, 10, 11]
If they are a match I would like to append it to a new list matching_list, if not I would to append non-matching values into another list non_matching_list.
This is what I tried so far,
matching_list = []
non_matching_list = []
for each_dict in sample_dict:
current_dict_values = []
for key, value_list in each_dict.items():
temp_dict_values = []
for value in value_list:
temp_dict_values.append(value)
.... don't know how to keep track of key 1's first list of lists values.
I was thinking of creating a temporary list to keep track of key 1 list values, but I am stuck and not sure how to proceed.
My final output should be like this:
matching_list = [[3,4,6,7,8,9,10], [1,2,3], []]
non_matching_list = [[1,2,5,11],[4,5,6,10],[1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11]]
How can I achieve my output? Any ideas would be great.
This can be achieved by converting lists to sets to make operations like symmetric_difference() and intersection() for your non_matching_list and matching_list respectively.
Here is one of the solutions:
matching_list, non_matching_list = [], []
for lists1, lists2 in zip(sample_dict[0].values(), sample_dict[1].values()):
for l1, l2 in zip(lists1, lists2):
matching_list.append(list(set(l1) & set(l2)))
non_matching_list.append(list(set(l1).symmetric_difference(set(l2))))
Note that using set(l1) & set(l2) is same as set(l1).intersection(set(l2)), so basically it's an intersection operation here.
I'm also using builtin zip() function to aggregate elements from each of the iterables ( both lists ).
I have the following array [1, 4, 7, 9, 2, 10, 5, 8] and I need to separate the array in 3 different arrays: one for values between 0 and 3, anther for 3 to 6 and anther for 6 and 25.The result must be something like that:
array1 = [1, 2]
array2 = [4, 5]
array3 = [7, 9, 10, 8]
Any idea about how to do it simple?
First, define your "pole" numbers
Second, generate your intervals from those "pole" numbers
Third, define as many lists as there are intervals.
Then for each interval, scan the list and appends items in the relevant list if they belong to the interval
code:
source = [1, 4, 7, 9, 2, 10, 5, 8]
poles = (0,3,6,25)
intervals = [(poles[i],poles[i+1]) for i in range(len(poles)-1)]
# will generate: intervals = [(0,3),(3,6),(6,25)]
output = [list() for _ in range(len(intervals))]
for out,(start,stop) in zip(output,intervals):
for s in source:
if start <= s <stop:
out.append(s)
print(output)
result:
[[1, 2], [4, 5], [7, 9, 10, 8]]
This solution has the advantage of being adaptable to more than 3 lists/intervals by adding more "pole" numbers.
EDIT: There's a nice & fast solution (O(log(N)*N)) if the output lists order don't matter:
first sort the input list
then generate the sliced sub-lists using bisect which returns insertion position of the provided numbers (left & right)
like this:
import bisect
source = sorted([1, 4, 7, 9, 2, 10, 5, 8])
poles = (0,3,6,25)
output = [source[bisect.bisect_left(source,poles[i]):bisect.bisect_right(source,poles[i+1])] for i in range(len(poles)-1)]
print(output)
result:
[[1, 2], [4, 5], [7, 8, 9, 10]]
You can do that in a very simple way using a combination of a for loop and range functions:
lists = ([], [], [])
for element in [1, 4, 7, 9, 2, 10, 5, 8]:
if element in range(0, 3):
lists[0].append(element)
elif element in range(3, 6):
lists[1].append(element)
elif element in range(6, 25):
lists[2].append(element)
array1, array2, array3 = lists
"One-line" solution using set.intersection(*others) and range(start, stop[, step]) functions:
l = [1, 4, 7, 9, 2, 10, 5, 8]
l1, l2, l3 = (list(set(l).intersection(range(3))), list(set(l).intersection(range(3,6))), list(set(l).intersection(range(6,25))))
print(l1)
print(l2)
print(l3)
The output:
[1, 2]
[4, 5]
[8, 9, 10, 7]
https://docs.python.org/3/library/stdtypes.html?highlight=intersection#set.intersection
I have a list like [[1, 2, 4], [2, 5], [0, 3, 7, 8], [12, 3, 6], [18, 14]]. How can I get a list that contains lists of all the lists that contain overlapping elements added together? For the example input, the result should be [[1, 2, 4, 5], [0, 3, 6, 7, 8, 12], [14, 18]].
a = [[1, 2, 4], [2, 5], [0, 3, 7, 8], [12, 3, 6], [18, 14]]
result = []
for s in a:
s = set(s)
for t in result:
if t & s:
t.update(s)
break
else:
result.append(s)
This will go one-by-one through the list and create a set from the current sublist (s). Then it will check in the results, if there is another set t that has a non-empty intersection with it. If that’s the case, the items from s are added to that set t. If there is no t with a non-empty intersection, then s is a new independent result and can be appended to the result list.
A problem like this is also a good example for a fixed-point iteration. In this case, you would look at the list and continue to merge sublists as long as you could still find lists that overlap. You could implement this using itertools.combinations to look at pairs of sublists:
result = [set(x) for x in a] # start with the original list of sets
fixedPoint = False # whether we found a fixed point
while not fixedPoint:
fixedPoint = True
for x, y in combinations(result, 2): # search all pairs …
if x & y: # … for a non-empty intersection
x.update(y)
result.remove(y)
# since we have changed the result, we haven’t found the fixed point
fixedPoint = False
# abort this iteration
break
One way I can think of doing this is through recursion. Start with one item, then loop until you find every number it's connected to. For each of these numbers, you must do the same. Hence the recursion. To make it more efficient, store numbers you've visited in a list and check it at the beginning of each recursive sequence to make sure you don't repeat any explorations.
A two liner:
a_set = [set(x) for x in a]
result = [list(x.union(y)) for i,x in enumerate(a_set) for y in a_set[i:]
if x.intersection(y) and x != y]
I have left the last step for you:
a = [[1, 2, 4], [2, 5], [0, 3, 7, 8], [12, 3, 6], [18, 14]]
result = [[1, 2, 4, 5], [0, 3, 6, 7, 8, 12], [14, 18]]
# each sub list
result2 = []
count = 0
print a
for sub_list in a:
print count
print "sub_list: " + str(sub_list)
a.pop(count)
print "a: " + str(a)
#each int
sub_list_extend_flag = False
for int_in_sub_list in sub_list:
print "int_in_sub_list: " + str(int_in_sub_list)
for other_sub_list in a:
print "current_other_sub_list: " + str(other_sub_list)
if int_in_sub_list in other_sub_list:
sub_list_extend_flag = True
other_sub_list.extend(sub_list)
result2.append(list(set(other_sub_list)))
if not sub_list_extend_flag:
result2.append(sub_list)
count += 1
print result2
Simple answer:
a = [[1, 2, 4], [2, 5], [0, 3, 7, 8], [12, 3, 6], [18, 14]]
for x in a:
for y in x:
print y
its more simple than first one:
box=[]
a = [[1, 2, 4], [2, 5], [0, 3, 7, 8], [12, 3, 6], [18, 14]]
for x in a:
for y in x:
box.append(y)
print box
Result:[1, 2, 4, 2, 5, 0, 3, 7, 8, 12, 3, 6, 18, 14]
And with this, you can compare the numbers:
box=[]
box2=""
a = [[1, 2, 4], [2, 5], [0, 3, 7, 8], [12, 3, 6], [18, 14]]
for x in a:
for y in x:
box.append(y)
print box
for a in box:
box2+=str(a)
print box2
Result: 12425037812361814
Also you can make it more cute:
print " ".join(box2)
Result: 1 2 4 2 5 0 3 7 8 1 2 3 6 1 8 1 4
I have a problem with "pairing" arrays into one (by index). Here is an example:
INPUT:
inputArray = [[0, 1, 2, 3, 4], [2, 3, 5, 7, 8], [9, 6, 1]]
EXPECTED OUTPUT:
outputArray =
[[0,2,9],
[1,3,6],
[2,5,1],
[3,7,chooseRandom()],
[4,8,chooseRandom()]]
Questions:
How to avoid "out of range" "index error" problem
How to write chooseRandom() to choose N neighbour
Answers:
[SOLVED] Solutions provided by #jonrsharpe & #Christian & #Decency works as
expected
Clarification:
By N neighbour I mean:
I'm using python but feel free to share your thoughts in any language.
I think the following will do what you want:
from itertools import izip_longest # 'zip_longest' in Python 3.x
from random import choice
# Step 1
outputArray = list(map(list, izip_longest(*inputArray)))
# Step 2
for index, arr in enumerate(outputArray):
if any(item is None for item in arr):
valid = [item for item in arr if item is not None]
outputArray[index] = [choice(valid) if item is None else item
for item in arr]
This has two steps:
Combine all sub-lists of inputArray to the length of the longest sub-array, filling with None: [[0, 2, 9], [1, 3, 6], [2, 5, 1], [3, 7, None], [4, 8, None]]; and
Work through the outputArray, finding any sub-lists that contain None and replacing the None with a random choice from the other items in the sub-list that aren't None.
Example output:
[[0, 2, 9], [1, 3, 6], [2, 5, 1], [3, 7, 3], [4, 8, 8]]
Here's my approach to the problem, in Python 3.4. I don't really know what you mean by "choose N neighbour" but it should be pretty easy to write that however you'd like in the context below.
inputArray = [[0, 1, 2, 3, 4], [2, 3, 5, 7, 8], [9, 6, 1]]
import itertools
zipped = itertools.zip_longest(*inputArray, fillvalue=None)
outputArray = [list(item) for item in zipped]
# [[0, 2, 9], [1, 3, 6], [2, 5, 1], [3, 7, None], [4, 8, None]]
# Now replace the sentinel None in our sublists
for sublist in outputArray:
for i, element in enumerate(sublist):
if element is None:
sublist[i] = chooseRandom()
print(outputArray)
Not the most pythonic way, but you could try using this code snipped, read the comments in the code below:
import itertools, random
inputArray = [ [0, 1, 2, 3, 4], [2, 3, 5, 7, 8], [9, 6, 1] ]
outputArray = []
max_length = max(len(e) for e in inputArray) # maximum length of the sublists in <inputArray>
i = 0 # to keep the index of sublists of <outputArray>
for j in range(max_length):
outputArray.append([]) # add new sublist
for e in inputArray: # iterate through each element of <inputArray>
try:
outputArray[i].append(e[j]) # try to append the number, if an exception is raised
# then the code in the <except> clause will be executed
except IndexError as e:
outputArray[i].append(random.randint(0, 10)) # add the random number
i += 1 # increase the sublists index on each iteration
print outputArray
# [[0, 2, 9], [1, 3, 6], [2, 5, 1], [3, 7, 3], [4, 8, 7]]
Note:
You may want to change the part
random.randint(0, 10)
to get the "N neighbour".
Let me know whether you like this code:
import random
array = [[0, 1, 2, 3, 4], [2, 3, 5, 7, 8], [9, 6, 1]]
max_len = max([len(l) for l in array])
dictionary = {}
for l in array:
for i in range(0,len(l)):
if dictionary.has_key(i):
dictionary[i].append(l[i])
else:
dictionary[i] = [l[i]]
for i in range(len(l),max_len):
if dictionary.has_key(i):
dictionary[i].append(random.choice(l))
else:
dictionary[i] = [random.choice(l)]
print dictionary.values()