Related
I have seen similar questions to mine, but nothing I researched really fixed my issue.
So, basically I want to split a list, in order to remove some items and concatenate it back. Those items correspond to indexes that are given by a list of tuples.
import numpy as np
arr = ['x','y','z','a','b','c','d','e','f','g',2,3,4]
indices = [(2,4),(7,9)] #INDEXES THAT NEED TO BE CUT OUT
print ([list1[0:s] +list1[s+1:e] for s,e in indices])
#Returns: [['x', 'y', 'z', 'a'], ['x', 'y', 'z', 'a', 'b', 'c', 'd', 'e', 'f']]
This code I have, which I got from one of the answers from this post nearly does what I need, but I tried to adapt it to loop over the first index of indices once but instead it does twice and it doesn't include the rest of the list.
I want my final list to split from zero index to the first item on first tuple and so on, using a for loop or some iterator.
Something like this,
`final_arr = arr[0:indices[0][0]] + arr[indices[0][1]:indices[1][0]] + arr[indices[1][1]:]<br/>
#Returns: [['x','y','a','b','c','f','g',2,3,4]]`
If someone could do it using for loops, it would be easier for me to see how you understand the problem, then after I can try to adapt to using shorter code.
Sort the indices using sorted and del the slices. You need reverse=True otherwise the indices of the later slices are incorrect.
for x, y in sorted(indices, reverse=True):
del(arr[x:y])
print(arr)
>>> ['x', 'y', 'b', 'c', 'd', 'g', 2, 3, 4]
This is the same result as you get with
print(arr[0:indices[0][0]] + arr[indices[0][1]:indices[1][0]] + arr[indices[1][1]:])
>>> ['x', 'y', 'b', 'c', 'd', 'g', 2, 3, 4]
arr = ['x','y','z','a','b','c','d','e','f','g',2,3,4]
indices = [(2,4),(7,9)] #INDEXES THAT NEED TO BE CUT OUT
import itertools
ignore = set(itertools.chain.from_iterable(map(lambda i: range(*i), indices)))
out = [c for idx, c in enumerate(arr) if idx not in ignore]
print(out)
print(arr[0:indices[0][0]] + arr[indices[0][1]:indices[1][0]] + arr[indices[1][1]:])
Output,
['x', 'y', 'b', 'c', 'd', 'g', 2, 3, 4]
['x', 'y', 'b', 'c', 'd', 'g', 2, 3, 4]
Like this:
import numpy as np
arr = ['x','y','z','a','b','c','d','e','f','g',2,3,4]
indices = [(2,4),(7,9)] #INDEXES THAT NEED TO BE CUT OUT
print ([v for t in indices for i,v in enumerate(arr) if i not in range(t[0],t[1])])
Output:
['x', 'y', 'z', 'a', 'b', 'c', 'd', 'e', 'f', 'g', 2, 3, 4, 'x', 'y', 'z', 'a', 'b', 'c', 'd', 'e', 'f', 'g', 2, 3, 4]
1- If you can remove the list items:
I using the example for JimithyPicker. I change the index list (removed items), because always that one index was removed the size of list change.
arr = ['x','y','z','a','b','c','d','e','f','g',2,3,4]
indices = [2,5,5] #INDEXES THAT NEED TO BE CUT OUT
for index in indices:
arr.pop(index)
final_arr = [arr]
print(final_arr)
Output:
[['x', 'y', 'a', 'b', 'c', 'f', 'g', 2, 3, 4]]
2- If you can't remove items:
In this case is necessary change the second index! The number doesn't match with output that you want.
The indices = [(2,4),(7,9)] has the output: ['x', 'y', 'a', 'b', 'c', 'd', 'f', 'g', 2, 3, 4]
arr = ['x','y','z','a','b','c','d','e','f','g',2,3,4]
indices = [(2,4),(6,9)] #INDEXES THAT NEED TO BE CUT OUT
final_arr = arr[0:indices[0][0]] + arr[indices[0][1]-1:indices[1][0]] + arr[indices[1][1]-1:]
print(final_arr)
Output:
['x','y','a','b','c','f','g',2,3,4]
Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 5 years ago.
Improve this question
I have a list:
l = ['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i']
Is there a way to create a list of lists so that:
l = [['a', 'b', 'c'], ['d', 'e', 'f'], ['g', 'h', 'i']]
And would it be possible to create the list of lists where the lists are of different sizes? For example:
l = [['a', 'b'], ['c', 'd', 'e', 'f'], ['g'], ['h', 'i']]
1 . For a multi-dimensioned list of defined inner list size :
>>> inner_size = 3
>>> out = [ l[i:i+inner_size] for i in range(0, len(l), inner_size) ]
>>> out
=> [['a', 'b', 'c'], ['d', 'e', 'f'], ['g', 'h', 'i']]
2 . For a multi-dimensioned list of random inner list size (this is kind of chunky unfortunately) :
>>> import random
>>> i=0
>>> out = []
>>> while i<len(l):
left_out = len(l) - i
inner_size = random.randint(1,left_out)
out.append(l[i: i+inner_size])
i += inner_size
>>> out
=> [['a'], ['b'], ['c', 'd', 'e', 'f', 'g'], ['h', 'i']]
For a consistent chunk size n, you can do:
l = ['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i']
n = 3
l2 = [l[i:i + n] for i in range(0, len(l), n)]
l2
# [['a', 'b', 'c'], ['d', 'e', 'f'], ['g', 'h', 'i']]
Given split indexes (which you can easily generate from a list of chunk sizes), you can produce custom slices:
splits = [0, 2, 6, 7, 9]
l2 = [l[start:end] for start, end in zip(splits, splits[1:])]
l2
# [['a', 'b'], ['c', 'd', 'e', 'f'], ['g'], ['h', 'i']]
Here is a simple solution, you can set your own chunk sizes in the variable chunk_sizes either as a list or tuple or an integer
def chunk_list(l,chunk_sizes):
if isinstance(chunk_sizes,int):
for i in range(0,len(l),chunk_sizes):
yield l[i:i + chunk_sizes]
else:
start = 0
for size in chunk_sizes:
if start < len(l):
yield l[start:start + size]
start += size
l = ['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i']
# custom chunk_sizes list
chunk_sizes = [2,4,1,2]
print ([sl for sl in chunk_list(l,chunk_sizes)])
#prints [['a', 'b'], ['c', 'd', 'e', 'f'], ['g'], ['h', 'i']]
# integer chunk_sizes
chunk_sizes = 3
print ([sl for sl in chunk_list(l,chunk_sizes)])
#prints [['a', 'b', 'c'], ['d', 'e', 'f'], ['g', 'h', 'i']]
This question already has answers here:
How do I clone a list so that it doesn't change unexpectedly after assignment?
(24 answers)
Closed 6 years ago.
I am using a recursive function on a list of lists with an accumulator, but instead of creating the right list of lists, it makes a list with duplicates of the last item inserted in the accumulator. I recreated the problem in a much simpler recursive function and list. This function takes a list of lists and makes 2 copies and reverses them n times.
def recursauto(x, n, instSet):
#Base Case
if(n==0):
instSet.append(x)
print(x) #Print to see what SHOULD be added
else:
temp = [x]*(2) # Make a list with 2 copies of the original list
for i in range(len(temp)):
temp[i][i] = temp[i][i][::-1] # Make the list backwards
for i in range(2):
recursauto(temp[i], n-1, instSet) #Input each element
MyList = [] #Empyt list for accumulator
print("Correct output:")
recursauto([["A", "l", "e", "x"], ["A", "b", "d", "a", "l", "a", "h"]], 2, MyList)
print("Wrong printed list:")
for i in MyList:
print(i) #Print what is in the accumulator
The output comes out wrong and the accumulator does not have the right things that were put into it.
Correct output:
[['A', 'l', 'e', 'x'], ['A', 'b', 'd', 'a', 'l', 'a', 'h']]
[['A', 'l', 'e', 'x'], ['A', 'b', 'd', 'a', 'l', 'a', 'h']]
[['x', 'e', 'l', 'A'], ['h', 'a', 'l', 'a', 'd', 'b', 'A']]
[['x', 'e', 'l', 'A'], ['h', 'a', 'l', 'a', 'd', 'b', 'A']]
Wrong printed list:
[['x', 'e', 'l', 'A'], ['h', 'a', 'l', 'a', 'd', 'b', 'A']]
[['x', 'e', 'l', 'A'], ['h', 'a', 'l', 'a', 'd', 'b', 'A']]
[['x', 'e', 'l', 'A'], ['h', 'a', 'l', 'a', 'd', 'b', 'A']]
[['x', 'e', 'l', 'A'], ['h', 'a', 'l', 'a', 'd', 'b', 'A']]
I know that there is an easier way to do this, but the function I'm actually making requires recursion. Like I said, this is just a simplified recreation of the problem I am having.
temp = [x]*(2)
The above line does not create a list of two copies of the original list; in fact, it just stores a reference to the same original list twice. If you want a distinct copy of x, try using the list copy constructor like temp = [list(x), list(x)] or alternatively the shallow copy method [x.copy() x.copy()].
See the below example.
>>> ls = ['a']
>>> dup = [ls] * 2
>>> dup
[['a'], ['a']]
>>> ls.append('b')
>>> dup
[['a', 'b'], ['a', 'b']]
How do you append each item of one list to each sublist of another list?
a = [['a','b','c'],['d','e','f'],['g','h','i']]
b = [1,2,3]
Result should be:
[['a','b','c',1],['d','e','f',2],['g','h','i',3]]
Keep in mind that I want to do this to a very large list, so efficiency and speed is important.
I've tried:
for sublist,value in a,b:
sublist.append(value)
it returns 'ValueError: too many values to unpack'
Perhaps a listindex or a listiterator could work, but not sure how to apply here
a = [['a','b','c'],['d','e','f'],['g','h','i']]
b = [1,2,3]
for ele_a, ele_b in zip(a, b):
ele_a.append(ele_b)
Result:
>>> a
[['a', 'b', 'c', 1], ['d', 'e', 'f', 2], ['g', 'h', 'i', 3]]
The reason your original solution did not work, is that a,b does create a tuple, but not what you want.
>>> z = a,b
>>> type(z)
<type 'tuple'>
>>> z
([['a', 'b', 'c'], ['d', 'e', 'f'], ['g', 'h', 'i']], [1, 2, 3])
>>> len(z[0])
3
>>> for ele in z:
... print ele
...
[['a', 'b', 'c'], ['d', 'e', 'f'], ['g', 'h', 'i']] #In your original code, you are
[1, 2, 3] #unpacking a list of 3 elements
#into two values, hence the
#'ValueError: too many values to unpack'
>>> zip(a,b) # using zip gives you what you want.
[(['a', 'b', 'c'], 1), (['d', 'e', 'f'], 2), (['g', 'h', 'i'], 3)]
Here is a simple solution:
a = [['a','b','c'],['d','e','f'],['g','h','i']]
b = [1,2,3]
for i in range(len(a)):
a[i].append(b[i])
print(a)
One option, using list comprehension:
a = [(a[i] + b[i]) for i in range(len(a))]
Just loop through the sublists, adding one item at a time:
for i in range(0,len(listA)):
listA.append(listB[i])
You can do:
>>> a = [['a','b','c'],['d','e','f'],['g','h','i']]
>>> b = [1,2,3]
>>> [l1+[l2] for l1, l2 in zip(a,b)]
[['a', 'b', 'c', 1], ['d', 'e', 'f', 2], ['g', 'h', 'i', 3]]
You can also abuse a side effect of list comprehensions to get this done in place:
>>> [l1.append(l2) for l1, l2 in zip(a,b)]
[None, None, None]
>>> a
[['a', 'b', 'c', 1], ['d', 'e', 'f', 2], ['g', 'h', 'i', 3]]
In Python, I have two lists that either have equal number of elements (e.g. 8 and 8) or one less than the other (e.g. 7 and 8; 3 and 4):
list1 = ['A', 'B', 'C', 'D']
list2 = ['E', 'F', 'G', 'H']
or
list3 = ['A', 'B', 'C']
list4 = ['D', 'E', 'F', 'G']
I'm trying to figure out the best way to build an algorithm that will switch the last half of the first list with the first half of the last list, resulting in this, when both lists have an even number of elements:
switched_list1 = ['A', 'B', 'E', 'F']
switched_list2 = ['C', 'D', 'G', 'H']
…and this when the one of the lists has an odd number:
switched_list3 = ['A', 'D', 'E']
switched_list4 = ['B', 'C', 'F', 'G']
What's the most efficient way to build an algorithm that can switch list elements like this?
list1 = ['A', 'B', 'C']
list2 = ['D', 'E', 'F', 'G']
nlist1 = len(list1)/2
nlist2 = len(list2)/2
new1 = list1[:nlist1] + list2[:nlist2]
new2 = list1[nlist1:] + list2[nlist2:]
print new1
print new2
produces
['A', 'D', 'E']
['B', 'C', 'F', 'G']
>>> def StrangeSwitch(list1,list2):
return (list1[:len(list1)/2]+list2[:len(list2)/2],list1[len(list1)/2:]+list2[len(list2)/2:])
>>> list1 = ['A', 'B', 'C', 'D']
>>> list2 = ['E', 'F', 'G', 'H']
>>> (list1,list2)=StrangeSwitch(list1,list2)
>>> list1
['A', 'B', 'E', 'F']
>>> list2
['C', 'D', 'G', 'H']
>>> list3 = ['A', 'B', 'C']
>>> list4 = ['D', 'E', 'F', 'G']
>>> (list3,list4)=StrangeSwitch(list3,list4)
>>> list3
['A', 'B', 'C']
>>> list4
['B', 'C', 'F', 'G']
>>>
Reading the Comments by OP I would take the priviledge of proposing another approach
>>> def StrangeSwitchFast(list1,list2):
#return (list1[:len(list1)/2]+list2[:len(list2)/2],list1[len(list1)/2:]+list2[len(list2)/2:])
return (list(itertools.chain(itertools.islice(list1,0,len(list1)/2),itertools.islice(list2,0,len(list2)/2))),
list(itertools.chain(itertools.islice(list1,len(list1)/2,None),itertools.islice(list2,len(list2)/2,None))))
The above doesn't create any temporary list and if OP desires to use it as an iterator rather than a list for the downstream processing, then the list can be safely dropped from the function and can be left to return as a tuple of iterators.