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
Related
Working on some example questions, the particular one asks to make a function which would take a list and return a new one which would make every ascending sublist in the list go in descending order and leave the descending sublists as they are. For example, given the list [1,2,3,4,5], I need the list [5,4,3,2,1] or given a list like [1,2,3,5,4,6,7,9,8] would return [5,3,2,1,9,7,6,4,8]
Here's what I have so far, but it does not do anything close to what I'd like it to do:
def example3(items):
sublst = list()
for i in items:
current_element = [i]
next_element = [i+1]
if next_element > current_element:
sublst = items.reverse()
else:
return items
return sublst
print (example3([1,2,3,2])) #[[1, 2, 3, 2], [1, 2, 3, 2], [1, 2, 3, 2], [1, 2, 3, 2]]
EDIT:
I feel like people are a little confused as to what I want to do in this case, heres a better example of what I'd like my function to do. Given a list like: [5, 7, 10, 4, 2, 7, 8, 1, 3] I would like it to return [10, 7, 5, 4, 8, 7, 2, 3, 1]. As you can see all the sublists that are in descending order such as ([5,7,10]) gets reversed to [10, 7, 5].
It was a bit challenging to figure out what you need.
I think you want something like as follows:
import random
l = [5, 7, 10, 4, 2, 7, 8, 1, 3]
bl =[]
while True:
if len(l) == 0:
break
r = random.randint(0, len(l))
bl.extend(l[r:None:-1])
l = l[r+1:]
print(bl)
Out1:
[10, 7, 5, 4, 8, 7, 2, 3, 1]
Out2:
[10, 7, 5, 2, 4, 1, 8, 7, 3]
Out3:
[3, 1, 8, 7, 2, 4, 10, 7, 5]
Out4:
[2, 4, 10, 7, 5, 3, 1, 8, 7]
etc.
If you want a specific reverse random list:
import random
loop_number = 0
while True:
l = [5, 7, 10, 4, 2, 7, 8, 1, 3]
bl =[]
while True:
if len(l) == 0:
break
r = random.randint(0, len(l))
bl.extend(l[r:None:-1])
l = l[r+1:]
loop_number += 1
if bl == [10, 7, 5, 4, 8, 7, 2, 3, 1]:
print(bl)
print("I tried {} times".format(loop_number))
break
Out:
[10, 7, 5, 4, 8, 7, 2, 3, 1]
I tried 336 times
The general algorithm is to keep track of the current ascending sublist you are processing using 2 pointers, perhaps a "start" and "curr" pointer. curr iterates over each element of the list. As long as the current element is greater than the previous element, you have an ascending sublist, and you move curr to the next number. If the curr number is less than the previous number, you know your ascending sublist has ended, so you collect all numbers from start to curr - 1 (because array[curr] is less than array[curr - 1] so it can't be part of the ascending sublist) and reverse them. You then set start = curr before incrementing curr.
You will have to deal with the details of the most efficient way of reversing them, as well as the edge cases with the pointers like what should the initial value of start be, as well as how to deal with the case that the current ascending sublist extends past the end of the array. But the above paragraph should be sufficient in getting you to think in the right direction.
Below is list of arrays:
{'array_1': [1, 2, 3, 4], 'array_2': [3, 4, 5, 6], 'array_3': [7, 8, 9, 0]}
Code for array input:
def main():
a = int(input("Enter the number of array's: "))
size = int(input('Each array size: '))
arrays = dict()
for i in range(1, a + 1):
arrays['array_' + str(i)] = list(
map(lambda j: int(input('value: ')), [j for j in range(size)]))
print(arrays)
I want to add 'array_1' with array_2
Just for clarification, you have a dictionary of lists, not a list of arrays. I think this is what you're looking for
list_dict = {'array_1': [1, 2, 3, 4], 'array_2': [3, 4, 5, 6], 'array_3': [7, 8, 9, 0]}
[sum(items) for items in zip(list_dict['array_1'], list_dict['array_2'])]
this results in the list [4, 6, 8, 10] - I'm assuming that's what you mean by add array_1 and array_2
If by add you mean concatenate do this:
new_list = array['array_1'] + array['array_2']
else if you mean addition of individual values you can do:
from operator import add
new_array = list(map(add,array['array_1'],array['array_2']))
If you want to sum element wise then
d= {'array_1': [1, 2, 3, 4], 'array_2': [3, 4, 5, 6], 'array_3': [7, 8, 9, 0]}
[sum(x) for x in zip(*d.values())] # will add elements from all the lists
Output:
[11, 14, 17, 10]
going along the same lines if you just want to add lists corresponding to some keys then you can filter the keys to create a new dict and use it in a same way
[sum(x) for x in zip(*{key:value for key,value in d.items() if key in ['array_1','array_2']}.values())]
Output
[4, 6, 8, 10]
I am trying to figure out how to append elements from the list into a pattern where I put them into the nested lists.
For example:
members = [1, 2, 3, 4, 5, 6, 7, 8, 9]
no_of_teams = int(input('no. of teams? '))
teams = [ [ ] for _ in range(no_of_teams)]
So that my output will end up looking like this:
no_of_teams? 2
teams = [ [1, 3, 5, 7, 9], [2, 4, 6, 8]]
if the user enters 3 then it will look like this:
teams = [[1, 4, 7], [2, 5, 8], [3, 6, 9]]
and for 7 it looks like
teams = [ [1, 8], [2, 9], [3], [4], [5], [6], [7] ]
A good way is to use slicing:
number = int(input(...))
members = list(range(1, 10))
chunks = len(members) // number
teams = [members[i*chunks:i*chunks+number]
for i in range(number)]
You could also use step size instead:
teams = [members[i::number]
for i in range(number)]
This will yield your desired output:
in each iteration, we start the slice at the next item in the list
the slice goes up in n steps
So, if n is 3, the 1st iteration will give a slice containing the indexes 0, 3, 6, 9..... since the step size is 3
The 2nd iteration gives indexes 1, 4, 7...
The 3rd iteration gives indexes 2, 5, 8...
Iteration stops here at the 3rd since n dictates this too.
You can slice it into the correct number of sublists:
slice_size = int(len(members) / no_of_teams)
teams = []
for i in range(no_of_teams):
teams.append( members[i * slice_size: i * slice_size + slice_size]
Given there are n teams, we can use list comprehension to construct n slices, such that the i-th element is assigned to the i mod n-th team:
teams = [ members[i::n] for i in range(n) ]
For example:
>>> n= 1
>>> [ members[i::n] for i in range(n) ]
[[1, 2, 3, 4, 5, 6, 7, 8, 9]]
>>> n= 2
>>> [ members[i::n] for i in range(n) ]
[[1, 3, 5, 7, 9], [2, 4, 6, 8]]
>>> n= 3
>>> [ members[i::n] for i in range(n) ]
[[1, 4, 7], [2, 5, 8], [3, 6, 9]]
You can slice the list:
teams = [members[i::no_of_teams] for i in range(no_of_teams)]
I want to split a list into sub-lists of a specified length. If the last chunk is not of the specified length, it will be augmented from the first element(s) of the list.
The below Python program produces equal sub-lists except for the last chunk.
def split_list(the_list, chunk_size):
result_list = []
while the_list:
result_list.append(the_list[:chunk_size])
the_list = the_list[chunk_size:]
return result_list
a_list = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
print split_list(a_list, 3)
Output:
[[1, 2, 3], [4, 5, 6], [7, 8, 9], [10]]
I want something like this:
[[1, 2, 3], [4, 5, 6], [7, 8, 9], [10, 1, 2]]
Let's try a generator-based solution using itertools.cycle and islice:
from itertools import cycle, islice
def split_list(lst, n):
it = cycle(lst)
for i in range(len(lst) // n + len(lst) % n):
yield list(islice(it, n))
Call the function like this:
>>> a_list = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
>>> list(split_list(a_list, 3))
[[1, 2, 3], [4, 5, 6], [7, 8, 9], [10, 1, 2]]
I personally prefer a generator here because the chunks are yielded one at a time, efficiently. If you want everything at once, you call list() on the result (like I've done).
Check to see whether you're going to be short in the last list chunk. If so, add exactly the needed quantity of elements, duplicated form the front of the list.
def split_list(the_list, chunk_size):
result_list = []
short = len(the_list) % chunk_size
if short:
# Add wrap-around elements from front of the_list
the_list.extend(the_list[:chunk_size-short])
while the_list:
result_list.append(the_list[:chunk_size])
the_list = the_list[chunk_size:]
return result_list
a_list = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
print(split_list(a_list, 3))
Output:
[[1, 2, 3], [4, 5, 6], [7, 8, 9], [10, 1, 2]]
One way is to use a list comprehension and then add part of the start of the list to the final group if needed.
def split_list(the_list, chunk_size):
chunks = [the_list[i:i+chunk_size] for i in range(0, len(the_list), chunk_size)]
chunks[-1] += the_list[:(chunk_size - len(the_list)) % chunk_size]
return chunks
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()