I want to take a list like:
x = [1,2,2,3,4,6,6]
and return a 2d list with the indexes of the repeating values:
[ [1,2], [5,6]]
I've tried the following:
new_list = []
i = 0
while i < len(x)-1:
if x[i] == x[i+1]:
new_list.append([x[i],x[i+1]]
i += 1
x is not necessarily sorted but has at least one series of repeating values. For example x can also be:
x = [1,4,2,3,3,3,7,0]
You can use itertools.groupby here.
from itertools import groupby
x=[1, 2, 2, 2, 3, 3, 4, 4, 6, 6, 6, 6, 6, 6, 8]
ranges=[list(g) for _,g in groupby(range(len(x)),lambda idx:x[idx])]
# [[0], [1, 2, 3], [4, 5], [6, 7], [8, 9, 10, 11, 12, 13], [14]]
# 1 2 2 2 3 3 4 4 6 6 6 6 6 6 8
final=[[r[0],r[-1]] for r in ranges if len(r)>1]
# [[1, 3], [4, 5], [6, 7], [8, 13]]
Pure Python approach:
x=[1, 2, 2, 2, 3, 3, 4, 4, 6, 6, 6, 6, 6, 6, 8]
out=[]
count=0
for i in range(1,len(x)):
prev=x[i-1]
if x[i]==prev:
count+=1
elif count and x[i]!=prev:
out.append([i-count-1,i-1])
count=0
if count:
out.append([i-count,i])
out
# [[1, 3], [4, 5], [6, 7], [8, 13]]
You can keep track of the current index and when the next element is equal to the value of the value in current_index, you append it to the result, but you need to increase the value of index until it's value will be different
x = [1, 2, 2, 3, 4, 6, 6]
result = []
cur_idx = 0
i = 1
while i < len(x):
if x[cur_idx] == x[i]:
result.append([cur_idx, x[cur_idx]])
# Increase value of i up to the index where there is different value
while i < len(x):
if x[cur_idx] != x[i]:
# Set cur_idx to the index of different value
cur_idx = i
i += 1
break
i += 1
else:
cur_idx = i
i += 1
print(result)
# [[1, 3], [5, 3]]
Try this code:
# Hello World program in Python
x = [1,2,2,3,4,6,6]
new_list = []
i = 0
indexes = []
while i < len(x)-1:
if x[i] == x[i+1]:
indexes.append(i)
indexes.append(i+1)
else:
indexes = list(set(indexes))
if len(indexes) != 0:
new_list.append(indexes)
indexes = []
i+=1
indexes = list(set(indexes))
if len(indexes) != 0:
new_list.append(indexes)
print(new_list)
Result:
[[1, 2], [5, 6]]
Try this.
def repeating_values( initital_list):
cache = {}
result = []
for i, element in enumerate(initital_list):
if element in cache:
result.append([cache[initital_list[i]], i])
else:
cache[element] = i
return result
For your input
x = [1,2,2,3,4,6,6]
print(repeating_values(x))
Result
[[1, 2], [5, 6]]
Related
Given that I have a list of numbers:
raw_list = [10, 9, 2, 8, 1, 3, 5, 4, 6, 7,11]
I want to separate it to top N's three times. Which means I want to rank them.
# Top 6 rank as 3
# Next Top 4 rank as 2
# Last Top 1 rank as 1
ranked_list = [3, 3, 2, 3, 1, 2, 2, 2, 3, 3, 3]
What I tried:
sorted(range(len(raw_list)), key=lambda i: raw_list[i])[-2:]
But this only gives indeces of the topmost and not the next topmost value of the list.
Use:
lst = [10, 9, 2, 8, 1, 3, 5, 4, 6, 7, 11]
indices = sorted(range(len(lst)), key=lambda i: lst[i], reverse=True)
ranked_list = [0 for _ in range(len(lst))]
for i, j in enumerate(indices):
if i < 6:
ranked_list[j] = 3
elif i < 6 + 4:
ranked_list[j] = 2
else:
ranked_list[j] = 1
print(ranked_list)
Output
[3, 3, 2, 3, 1, 2, 2, 2, 3, 3, 3]
Here's a different approach which is significantly faster than the accepted answer (if that's important):
Edited to show performance timings between the original and accepted answer because #funnydman wants proof
from timeit import timeit
L = [10, 9, 2, 8, 1, 3, 5, 4, 6, 7, 11]
def func1(list_):
slist = sorted(list_)
result = []
top6 = set(slist[5:])
top4 = set(slist[1:5])
for e in list_:
if e in top6:
result.append(3)
elif e in top4:
result.append(2)
else:
result.append(1)
return result
def func2(list_):
indices = sorted(range(len(list_)), key=lambda i: list_[i], reverse=True)
ranked_list = [0 for _ in range(len(list_))]
for i, j in enumerate(indices):
if i < 6:
ranked_list[j] = 3
elif i < 6 + 4:
ranked_list[j] = 2
else:
ranked_list[j] = 1
return ranked_list
for func in func1, func2:
print(func.__name__, timeit(lambda: func(L)))
Output:
func1 1.3904414890002954
func2 2.388311982000232
IIUC, this will work for you:
import pandas as pd
list(pd.cut(l, bins=[0, 1, 5, 11], labels=[1, 2, 3]))
Output:
[3, 3, 2, 3, 1, 2, 2, 2, 3, 3, 3]
The input is always strictly increasing. I could write this with a for loop and lots of if-else conditions, but is there some simple way? Here is an example:
input: [2,3,4,6,8,9]
output: [[0,1,2],[4,5]]
input: [1,2,3,4]
output: [[0,1,2,3]]
input: [0,1,2,4,6,7,8,10,12,13,14]
output: [[0,1,2], [4,5,6], [8,9,10]]
For example here is the code I wrote
def get_mergable_indices(sent_order):
mergable_indices = []
continuous_sents = [0]
for index, value in enumerate(sent_order):
if index == 0:
continue
else:
if value - sent_order[index-1] == 1:
continuous_sents.append(index)
else:
if len(continuous_sents)>1:
mergable_indices.append(continuous_sents)
continuous_sents = [index]
if len(continuous_sents)>1:
mergable_indices.append(continuous_sents)
return mergable_indices
It's too big want to reduce it
Maybe you can try this:
def get_mergable_indices(sent_order):
lst, res = [j-i for i, j in enumerate(sent_order)], []
ci = 0
for i in set(lst):
lci = lst.count(i)
if lci > 1:
res.append(list(range(ci, lci + ci)))
ci += lci
return res
output:
>>> get_mergable_indices([2,3,4,6,8,9])
[[0, 1, 2], [4, 5]]
>>> get_mergable_indices([1,2,3,4])
[[0, 1, 2, 3]]
>>> get_mergable_indices([0,1,2,4,6,7,8,10,12,13,14])
[[0, 1, 2], [4, 5, 6], [8, 9, 10]]
This can easily be done without using any module.
def get_mergable_indices(sent_order):
lst = sent_order
out = []
l = []
for a in range(max(lst)): # set range to the max number in the list.
try:
if lst[a]+1 == lst[a+1]: # check current number plus 1 is equal to next number
l.append(a)
l.append(a+1)
else: # if not equal then append l to the out list also set the l to an empty list.
if l:
out.append(list(set(l)))
l = []
except IndexError:
pass
out.append(list(set(l)))
return (out)
output
input: [2,3,4,6,8,9]
output: [[0,1,2],[4,5]]
input: [1,2,3,4]
output: [[0,1,2,3]]
input: [0,1,2,4,6,7,8,10,12,13,14]
output: [[0,1,2], [4,5,6], [8,9,10]]
This can accept any iterable sequence:
from itertools import pairwise
def get_mergable_indices(sent_order):
result = []
curr = []
for idx, (i, j) in enumerate(pairwise(sent_order)):
if j - i == 1:
curr.append(idx)
elif curr:
curr.append(idx)
result.append(curr)
curr = []
if curr:
curr.append(idx + 1)
result.append(curr)
return result
Output:
>>> get_mergable_indices([2, 3, 4, 6, 8, 9])
[[0, 1, 2], [4, 5]]
>>> get_mergable_indices(range(1, 5))
[[0, 1, 2, 3]]
>>> get_mergable_indices([0, 1, 2, 4, 6, 7, 8, 10, 12, 13, 14])
[[0, 1, 2], [4, 5, 6], [8, 9, 10]]
This is my approach:
def check_continuous(inp_list):
idx = idy = 0
res = [[]]
while idx < len(inp_list) - 1:
# Not append repeated indices
if inp_list[idx] - inp_list[idx+1] == -1: # If the next element is 1 higher, just check for -1
if idx not in res[idy]:
res[idy].append(idx)
if idx+1 not in res[idy]:
res[idy].append(idx+1)
else:
# Don't append empty lists
if res[idy]:
res.append([])
idy += 1
idx += 1
return res
print(check_continuous([2,3,4,6,8,9]))
# [[0, 1, 2], [4, 5]]
print(check_continuous([1,2,3,4]))
# [[0, 1, 2, 3]]
print(check_continuous([0,1,2,4,6,7,8,10,12,13,14]))
# [[0, 1, 2], [4, 5, 6], [8, 9, 10]]
I think this could be highly improved
As I have mentioned in the comments, np.diff can be a good choice in this regard. The accepted answer used two loops again, but is written in smaller form, and is not so different than other answers. The problem can be solved by Just NumPy as:
a = np.array([0, 1, 2, 4, 6, 7, 8, 10, 12, 13, 14])
diff = np.diff(a, prepend=a[0]-2) # [2 1 1 2 2 1 1 2 2 1 1]
diff_w = np.where(diff == 1)[0] # [ 1 2 5 6 9 10]
mask_ = np.diff(diff_w, prepend=diff_w[0]-2) # [2 1 3 1 3 1]
mask_ = mask_ != 1 # [ True False True False True False]
con_values = np.insert(diff_w, np.where(mask_)[0], diff_w[mask_] - 1) # [ 0 1 2 4 5 6 8 9 10]
# result = np.split(con_values, np.where(np.diff(con_values, prepend=con_values[0] - 1) != 1)[0])
result = np.split(con_values, np.where(np.diff(con_values, prepend=con_values[0] - 2) != 1)[0])[1:]
# [array([0, 1, 2], dtype=int64), array([4, 5, 6], dtype=int64), array([ 8, 9, 10], dtype=int64)]
I have tested this code on your examples and some others and it works. But, if there be any problem using other samples, it can be handled with some little changes by inspiration from this code. I wrote this code in separate parts to be understandable more. You can combine them in just one line if it is important for you.
Python - How can I write a python program to accept a List, and extract all elements whose frequency is greater than K? Please advise?
Sample I/O:
Input List:
[4, 6, 4, 3, 3, 4, 3, 4, 6, 6]
Input K:
2
Required Output : [4, 3, 6]
Use a list comprehension:
a = [4, 6, 4, 3, 3, 4, 3, 4, 6, 6]
k = 2
out = [i for i in set(a) if a.count(i) > k]
Use counter in python
list1 = [4, 6, 4, 3, 3, 4, 3, 4, 6, 6]
d = Counter(list1)
new_list = list([item for item in d if d[item] > 1])
print(new_list) #output: [4, 6, 3]
inputs = 0
user_list = []
while inputs < 8:
user_input = int(input("Enter a number: "))
user_list.append(user_input)
inputs += 1
input_list = [4, 6, 4, 3, 3, 4, 6, 6]
input_k = 2
def extract(x, y):
product = []
for i in x:
list_element = i
if list_element > y:
product.append(i)
else:
break
product = list(set(product))
return product
print(extract(user_list, input_k))
print(extract(input_list, input_k))
I want to create a multi dimensional Array out of normal array. When there is a 0 in my start array i want to change the row number by 1.
My start array looks like this:
arr = [1, 2, 3, 0, 4, 5, 6, 0, 7, 8, 9]
My futre multi array should look like this:
multi_arr = [[1, 2, 3],
[4, 5, 6],
[7, 8, 9]]
My code looks like this so far:
multi_arr = []
end = len(arr)
i = 0 #row
j = 0 #column
for h in range(end):
if arr[h] != 0:
j += 1
multi_arr[i][j]= arr[h]
elif arr[i] != 0:
i += 1
I always get a list index error with this code.
If you really want to work with lists, you dont need a column indexer. You can simply append the value to the correct list.
multi_arr = [[]] # start with a nested list, since your vector doesnt start with a 0
endi = len(arr)
i = 0 #row
for h in range(endi):
if arr[h] != 0:
multi_arr[i].append(arr[h])
else:
i += 1
multi_arr.insert(i,[]) # open new list
output:
[[1, 2, 3], [4, 5, 6], [7, 8, 9]]
This should do the job in a simpler way:
arr = [1, 2, 3, 0, 4, 5, 6, 0, 7, 8, 9]
multi_arr = []
temp_arr = []
for h in arr:
if h != 0:
temp_arr.append(h)
else:
multi_arr.append(temp_arr)
temp_arr = []
if h != 0: # Insert the last array it the last number wasn't 0
multi_arr.append(temp_arr)
print(multi_arr)
This is happening because at the point where you are trying set multi_arr[i][j], it is still a 1-d array. You can verify this with a print statement or a debugger - like so:
for h in range(end):
if arr[h] != 0:
print(multi_arr)
j += 1
multi_arr[i][j]= arr[h]
elif arr[i] != 0:
i += 1
I would definitely try something more pythonic for what you are trying to accomplish, reading the elements into a temp array and appending that temp array to multi array.
arr = [1, 2, 3, 0, 4, 5, 6, 0, 7, 8, 9]
multi_arr = []
temp_array = []
for item in arr:
if item == 0:
multi_arr.append(temp_array)
temp_array = []
else:
temp_array.append(item)
multi_arr.append(temp_array)
print(multi_arr)
You are declaring a 1D array and appending like 2D array
One solution two your Problem is :
arr=[1,2,3,4,5,6,7,8,9]
multi_arr=[]
end = len(arr)
a = []
counter =0
for i in arr :
if counter < 3 :
a.append(i)
counter += 1
else:
multi_arr.append(a)
a=[]
counter = 0
a.append(i)
counter += 1
multi_arr.append(a)
print(multi_arr)
Here is a yield approach:
def f(arr):
res = []
for x in arr:
if x == 0:
yield res
res = []
else:
res.append(x)
yield res
list(f(arr))
#> [[1, 2, 3], [4, 5, 6], [7, 8, 9]]
A different approach for you: super simple and no loop.
import numpy as np
arr = [1, 2, 3, 0, 4, 5, 6, 0, 7, 8, 9]
a = [i for i in arr if i]
x = arr[arr!=0] + 1
np.array(a).reshape([-1, x])
Output:
array([[1, 2, 3],
[4, 5, 6],
[7, 8, 9]])
And if you need lists, just use np.array(a).reshape([x, y]).tolist() instead.
One-liner:
After converting your list to a numpy array a = np.array(arr):
a[a!=0].reshape([-1, len(a) - np.count_nonzero(a)+1])
I have a list of of lists like this:
nestedList = [[0],[0,1,2,3,4,6,7,8,9],[0,1,2,3,4,6,7,8,9],[1,2,3]]
and I have another homogeneous (same length) list of elements that I want to use to split the nestedList
lengthList = [[1],[5,4],[5,4],[3]]
I tried:
def split(arr, size):
arrs = []
while len(arr) > size:
pice = arr[:size]
arrs.append(pice)
arr = arr[size:]
arrs.append(arr)
return arrs
for i,j in zip(nestedList,lengthList):
for k in j:
myNewList.append(split(i,k))
but it doesn't work 100% right.
The output it gives is:
myNewList = [[[0]], [[0, 1, 2, 3, 4], [6, 7, 8, 9]], [[0, 1, 2, 3], [4, 6, 7, 8], [9]], [[0, 1, 2, 3, 4], [6, 7, 8, 9]], [[0, 1, 2, 3], [4, 6, 7, 8], [9]], [[1, 2, 3]]]
instead of
[[[0], [[0, 1, 2, 3, 4], [6, 7, 8, 9]], [[0, 1, 2, 3], [4, 6, 7, 8,9]], [[1, 2, 3]]]
Any help would be appreciated.
nestedList = [[0],[0,1,2,3,4,6,7,8,9],[0,1,2,3,4,6,7,8,9],[1,2,3]]
lengthList = [[1],[5,4],[5,4],[3]]
answer = []
for lens,sub in zip(lengthList, nestedList):
answer.append([])
top = 0
for l in lens:
answer[-1].append(sub[top:top+l])
top += l
Output:
In [2]: answer
Out[2]:
[[[0]],
[[0, 1, 2, 3, 4], [6, 7, 8, 9]],
[[0, 1, 2, 3, 4], [6, 7, 8, 9]],
[[1, 2, 3]]]
try this code
# stackoverflow.com
# Python
# split list into nested lists by values in a loop (iterating values)
nestedList = [[0],[0,1,2,3,4,6,7,8,9],[0,1,2,3,4,6,7,8,9],[1,2,3]]
lengthList = [[1],[5,4],[5,4],[3]]
def toOneList (array):
oneList = []
if len(array) > 0:
for subList in array:
for x in subList:
oneList.append(x)
return oneList
def grouping(array, size):
newList = []
i = 0
for j in size:
newList.append(array[i:i+j])
i = i + j
return newList
nestedList = toOneList(nestedList)
lengthList = toOneList(lengthList)
print(grouping(nestedList, lengthList))
Here is the solution you need
# stackoverflow.com
# Python
# split list into nested lists by values in a loop (iterating values)
nestedList = [[0],[0,1,2,3,4,6,7,8,9],[0,1,2,3,4,6,7,8,9],[1,2,3]]
lengthList = [[1],[5,4],[5,4],[3]]
def toOneList (array):
oneList = []
if len(array) > 0:
for subList in array:
for x in subList:
oneList.append(x)
return oneList
def grouping(array, size):
newList = []
i = 0
for j in size:
newList.append(array[i:i+j])
i = i + j
return newList
nestedList = toOneList(nestedList)
lengthList = toOneList(lengthList)
print(grouping(nestedList, lengthList))