I have a list with an odd number of elements. I want to convert it into a specific size.
My code:
alist = ['a','b','c']
cols= 2
rows = int(len(alist)/cols)+1 # 2
anarray = np.array(alist.extend([np.nan]*((rows*cols)-len(months_list)))).reshape(rows,cols)
Present output:
ValueError: cannot reshape array of size 1 into shape (2,2)
Expected output:
anarray = [['a','b'],['c',nan]]
You can try:
out = np.full((rows,cols), np.nan, dtype='object')
out.ravel()[:len(alist)] = alist
Output:
array([['a', 'b'],
['c', nan]], dtype=object)
As a side note, this might be better for you:
rows = int(np.ceil(len(alist)/cols))
You can use list comprehension to achieve the result:
li = ['a','b','c']
l = len(li)
new_list = [li[x:x+2] for x in range(l // 2)]
if l % 2 != 0:
new_list.append([li[-1], None])
print(new_list) # [['a', 'b'], ['c', None]]
Try (without any external library)
import math
alist = ['a', 'b', 'c']
cols = 2
new_list = []
steps = math.ceil(len(alist) / cols)
start = 0
for x in range(0, steps):
new_list.append(alist[x * cols: (x + 1) * cols])
new_list[-1].extend([None for t in range(cols - len(new_list[-1]))])
print(new_list)
output
[['a', 'b'], ['c', None]]
Related
How to simplify and automate the following syntax so that i can achieve:
Assumptions:
lenght of x and y will alway be the same
the number of value in x and y will change
Objective:
print the value in y according to the corresponding number of time that show in x
Expected Output>>> ['a', 'a', 'b', 'b', 'b', 'c']
v = len(x)
x = [2, 3, 1]
y = ['a', 'b', 'c']
z = []
for i in range(x[0]):
z.append(y[0])
for i in range(x[1]):
z.append(y[1])
for i in range(x[2]):
z.append(y[2])
#if there there is forth value being added in both x and y, then it should repeat the step above#
print(z)
Look at using zip() function
z = []
for amount, item in zip(x, y):
for _ in range(amount):
z.append(item)
Or, shorter
z = []
for amount, item in zip(x, y):
z.extend(item for _ in range(amount))
You can use nested loop to do this:
x = [2, 3, 1]
y = ['a', 'b', 'c']
z = []
v = len(x)
for i in range(v):
for j in range(x[i]):
z.append(y[i])
print(z)
I'm just letting another possible solution that works.
x = [2, 3, 1]
y = ['a', 'b', 'c']
z = []
for idx in range(len(x)):
z += list(y[idx] * x[idx])
print(z)
x = [2, 3, 1]
y = ['a', 'b', 'c']
z = []
for i in range(len(x)):
z.extend([y[i]] * x[i])
print(z)
Gives output
['a', 'a', 'b', 'b', 'b', 'c']
this will work fine.
x = [2, 3, 1]
y = ['a', 'b', 'c']
z = []
for i in x:
for o in range(i):
z.append(y[x.index(i)])
print(z)
One with repeat and chain:
z = list(chain(*map(repeat, y, x)))
Try it online!
l1 = [['a', 'b', 'c'],
['a', 'd', 'c'],
['a', 'e'],
['a', 'd', 'c'],
['a', 'f', 'c'],
['a', 'e'],
['p', 'q', 'r']]
l2 = [1, 1, 1, 2, 0, 0, 0]
I have two lists as represented above. l1 is a list of lists and l2 is another list with some kind of score.
Problem: For all the lists in l1 with a score of 0 (from l2), find those lists which are either entirely different or have the least length.
For example: if i have the lists [1, 2, 3], [2, 3], [5, 7] all with score 0, i will choose [5, 7] because these elements are not present in any other lists and [2, 3] since it has an intersection with [1, 2, 3] but is of a smaller length.
How I do this now:
l = [x for x, y in zip(l1, l2) if y == 0]
lx = [(x, y) for x, y in zip(l1, l2) if y > 0]
c = list(itertools.combinations(l, 2))
un_usable = []
usable = []
for i, j in c:
intersection = len(set(i).intersection(set(j)))
if intersection > 0:
if len(i) < len(j):
usable.append(i)
un_usable.append(j)
else:
usable.append(j)
un_usable.append(i)
for i, j in c:
intersection = len(set(i).intersection(set(j)))
if intersection == 0:
if i not in un_usable and i not in usable:
usable.append(i)
if j not in un_usable and j not in usable:
usable.append(j)
final = lx + [(x, 0) for x in usable]
and final gives me:
[(['a', 'b', 'c'], 1),
(['a', 'd', 'c'], 1),
(['a', 'e'], 1),
(['a', 'd', 'c'], 2),
(['a', 'e'], 0),
(['p', 'q', 'r'], 0)]
which is the required result.
EDIT: to handle equal lengths:
l1 = [['a', 'b', 'c'],
['a', 'd', 'c'],
['a', 'e'],
['a', 'd', 'c'],
['a', 'f', 'c'],
['a', 'e'],
['p', 'q', 'r'],
['a', 'k']]
l2 = [1, 1, 1, 2, 0, 0, 0, 0]
l = [x for x, y in zip(l1, l2) if y == 0]
lx = [(x, y) for x, y in zip(l1, l2) if y > 0]
c = list(itertools.combinations(l, 2))
un_usable = []
usable = []
for i, j in c:
intersection = len(set(i).intersection(set(j)))
if intersection > 0:
if len(i) < len(j):
usable.append(i)
un_usable.append(j)
elif len(i) == len(j):
usable.append(i)
usable.append(j)
else:
usable.append(j)
un_usable.append(i)
usable = [list(x) for x in set(tuple(x) for x in usable)]
un_usable = [list(x) for x in set(tuple(x) for x in un_usable)]
for i, j in c:
intersection = len(set(i).intersection(set(j)))
if intersection == 0:
if i not in un_usable and i not in usable:
usable.append(i)
if j not in un_usable and j not in usable:
usable.append(j)
final = lx + [(x, 0) for x in usable]
Is there a better, faster & pythonic way of achieving the same?
Assuming I understood everything correctly, here is an O(N) two-pass algorithm.
Steps:
Select lists with zero score.
For each element of each zero-score list, find the length of the shortest zero-score list in which the element occurs. Let's call this the length score of the element.
For each list, find the minimum of length scores of all elements of the list. If the result is less than the length of the list, the list is discarded.
def select_lsts(lsts, scores):
# pick out zero score lists
z_lsts = [lst for lst, score in zip(lsts, scores) if score == 0]
# keep track of the shortest length of any list in which an element occurs
len_shortest = dict()
for lst in z_lsts:
ln = len(lst)
for c in lst:
len_shortest[c] = min(ln, len_shortest.get(c, float('inf')))
# check if the list is of minimum length for each of its chars
for lst in z_lsts:
len_lst = len(lst)
if any(len_shortest[c] < len_lst for c in lst):
continue
yield lst
I have a array
arr = [['a', 'b', 'a'], [1, 2, 3]
I need this to be spliited based on the first array values i.e based on 'a' or 'b'. So Expected output is
arr_out_a = [1, 3]
arr_out_b = [2]
How do I do it?
Please help me correct the question,if the way I'm using words like list and array might create confusion
Use collections.defaultdict():
In [82]: arr = [['a', 'b', 'a'], [1, 2, 3]]
In [83]: from collections import defaultdict
In [84]: d = defaultdict(list)
In [85]: for i, j in zip(*arr):
....: d[i].append(j)
....:
In [86]: d
Out[86]: defaultdict(<class 'list'>, {'b': [2], 'a': [1, 3]})
Basically just append them conditionally to predefined empty lists:
arr_out_a = []
arr_out_b = []
for char, num in zip(*arr):
if char == 'a':
arr_out_a.append(num)
else:
arr_out_b.append(num)
or if you don't like the zip:
arr_out_a = []
arr_out_b = []
for idx in range(len(arr[0])):
if arr[0][idx] == 'a':
arr_out_a.append(arr[1][idx])
else:
arr_out_b.append(arr[1][idx])
I have a problem with a list comprehension inside a loop. I want to add items from one list to an other.
I'm using map class and zip inside the list comprehension.
from pandas import Series, DataFrame
import pandas
x = ['a', 'b', 'c', 'd', 'e']
y = [2, 3, 6, 7, 4]
ser = {'A': Series(x), 'B': Series(y)}
df = DataFrame(ser)
targets = df['A'].tolist()
df['A1999'] = [i + 1 for i in df['B']]
df['A2000'] = [i + 2 for i in df['B']]
df['A2001'] = [i + 3 for i in df['B']]
df['A2002'] = [i + 1.7 for i in df['B']]
df['A2003'] = [i + 1.1 for i in df['B']]
y = range(1999, 2004)
gaps = []
for t in targets:
temp = []
years = []
for ele in y:
target = 'A' + str(ele)
new = df[target][df['A'] == t].tolist()
temp.append(new)
years.append(ele)
gap = [list(map(list, zip(years, item))) for item in temp]
gaps.append(gap)
And the output:
[[[[1999, 3]], [[1999, 4]], [[1999, 5]], [[1999, 3.7000000000000002]],
[[1999, 3.1000000000000001]]]...
What I'm looking for is:
[[[[1999, 3]], [[2000, 4]], [[2001, 5]], [[2002, 3.7000000000000002]],
[[2003, 3.1000000000000001]]]...
How can I fix the list comprehension in order to add all years from years list and not only the first (i.e. 1999)
I tried with this example, but I think I'm doing the same thing:
gap = [[[years[i], x] for i, x in enumerate(y)] for y in temp]
or
gap = [list(map(list, zip([[y] for y in years], item))) for item in temp]
Replace gap = with this
[list((x,y[0])) for x,y in zip(years,temp)]
Suppose I have an array of 2 columns. It looks like this
column1 = [1,2,3,...,830]
column2 = [a,b,c,...]
I want to have output in a print form of single columns, that includes value of both columns one by one. output form: column = [1,a,2,b ....]
I tried to do by this code,
dat0 = np.genfromtxt("\", delimiter = ',')
mu = dat0[:,0]
A = dat0[:,1]
print(mu,A)
R = np.arange(0,829,1)
l = len(mu)
K = np.zeros((l, 1))
txtfile = open("output_all.txt",'w')
for x in mu:
i = 0
K[i,0] = x
dat0[i,1] = M
txtfile.write(str(x))
txtfile.write('\n')
txtfile.write(str(M))
txtfile.write('\n')
print K
I do not understand your code completely, is the reference to numpy really relevant for your question? What is M?
If you have two lists of the same lengths you can get pairs of elements using the zip builtin.
A = [1, 2, 3]
B = ['a', 'b', 'c']
for a, b in zip(A, B):
print(a)
print(b)
This will print
1
a
2
b
3
c
I'm sure there is a better way to do this, but one method is
>>> a = numpy.array([[1,2,3], ['a','b','c'],['d','e','f']])
>>> new_a = []
>>> for column in range(0,a.shape[1]): # a.shape[1] is the number of columns in a
... for row in range(0,a.shape[1]): # a.shape[0] is the number of rows in a
... new_a.append(a[row][column])
...
>>> numpy.array(new_a)
array(['1', 'a', 'd', '2', 'b', 'e', '3', 'c', 'f'],
dtype='|S1')