looping over list and delete items in for loop - python

I have list which has more than 1000 elements
and i have a page where i must add those elements from the list but the thing is the page only accepts 40 entries at a time.
so what i am tring to do is grab 40 elements from the list then submit those elements to the page using for loop then delete these elements from the list and grab 40 elements again, i need to do this till all the elements from the list are submitted to the page.
this is what i have done so far and failed
mylist1 = ['1','2','3','4','5','6','7','8','9','10','10','11',]
def listget():
newlistget = [x for x in mylist1]
return newlistget
while True:
for x in listget():
for i in range(0,40):
#do stuff
mylist1.remove(mylist1[i])
if not listget():
break

You don't need to alter your initial data; instead, you can request successive chunks of a given size from it:
something like this:
In this example, if len(seq) is not a multiple of chunk_size, the last values will be what's left in the sequence.
The keyword argument start can optionally be set to start the chunks at an arbitrary location.
def chunks(seq, chunk_size, start=0):
while start < len(seq):
end = chunk_size + start
yield(seq[start: end])
start = end
if __name__ == '__main__':
mylist = ['1', '2', '3', '4', '5', '6', '7', '8', '9', '10', '10', '11', ]
for chunk in chunks(mylist, 3):
print(chunk)
output:
['1', '2', '3']
['4', '5', '6']
['7', '8', '9']
['10', '10', '11']

Why can't you slice the list every time, because remove will be a costly operation
list1=[i for i in range(1234)] #some huge list
print(len(list1)) #1234
j=40
while(j<len(list1)):
new_list=list1[j-40:j] #slice the list for 40 elements
print(len(new_list))
''' add your processing here (like submitting)'''
j+=40
new_list=list1[j-40:] #the last part of the list
print(len(new_list))
A generalized version to break a list into even sized chunks :
n=40 #In this case
new_list = [my_list[i * n:(i + 1) * n] for i in range((len(my_list) + n - 1) // n )]
new_list is a list of lists with each list of size 40 (Maybe except the last one)

Even tho i don't fully understand the question, but i can do something that creates a list of list containing each forty elemnts, like:
print([mylist1[i:i+40] for i in range(0,len(mylist1),40)])
Demo:
mylist1 = list(range(1000))
print([mylist1[i:i+40] for i in range(0,len(mylist1),40)])

Related

Parse a list into a list of lists in python

I am trying to figure out how to parse a list into a list of lists.
tileElements = browser.find_element(By.CLASS_NAME, 'tile-container')
tileHTML = (str(tileElements.get_attribute('innerHTML')))
tileNUMS = re.findall('\d+',tileHTML)
NumTiles = int(len(tileNUMS)/4)
#parse out list, each 4 list items are one tile
print(str(tileNUMS))
print(str(NumTiles))
TileList = [[i+j for i in range(len(tileNUMS))]for j in range (NumTiles)]
print(str(TileList))
The first part of this code works find and gives me a list of Tile Numbers:
['2', '3', '1', '2', '2', '4', '4', '2']
However, what I need is a list of lists made out of this and that is where I am getting stuck.
The list of lists should be 4 elements long and look like this:
[['2', '3', '1', '2'] , ['2', '4', '4', '2']]
It should be able to do this for as many tiles as there are in the game (up to 19 I believe). It would be really nice if when the middle numbers are repeated that the two outside numbers are replaced with the latest value from the source list.
You can use a list comprehension to get slices from the list like so.
elements = ['2', '3', '1', '2', '2', '4', '4', '2']
size = 4
result = [elements[i:i+size] for i in range(0, len(elements), size)]
(By the way, there's no need to cast things into str to print them, and tileHTML is probably already a string, too.)

how to remove the first occurence of an integer in a list

this is my code:
positions = []
for i in lines[2]:
if i not in positions:
positions.append(i)
print (positions)
print (lines[1])
print (lines[2])
the output is:
['1', '2', '3', '4', '5']
['is', 'the', 'time', 'this', 'ends']
['1', '2', '3', '4', '1', '5']
I would want my output of the variable "positions" to be; ['2','3','4','1','5']
so instead of removing the second duplicate from the variable "lines[2]" it should remove the first duplicate.
You can reverse your list, create the positions and then reverse it back as mentioned by #tobias_k in the comment:
lst = ['1', '2', '3', '4', '1', '5']
positions = []
for i in reversed(lst):
if i not in positions:
positions.append(i)
list(reversed(positions))
# ['2', '3', '4', '1', '5']
You'll need to first detect what values are duplicated before you can build positions. Use an itertools.Counter() object to test if a value has been seen more than once:
from itertools import Counter
counts = Counter(lines[2])
positions = []
for i in lines[2]:
counts[i] -= 1
if counts[i] == 0:
# only add if this is the 'last' value
positions.append(i)
This'll work for any number of repetitions of values; only the last value to appear is ever used.
You could also reverse the list, and track what you have already seen with a set, which is faster than testing against the list:
positions = []
seen = set()
for i in reversed(lines[2]):
if i not in seen:
# only add if this is the first time we see the value
positions.append(i)
seen.add(i)
positions = positions[::-1] # reverse the output list
Both approaches require two iterations; the first to create the counts mapping, the second to reverse the output list. Which is faster will depend on the size of lines[2] and the number of duplicates in it, and wether or not you are using Python 3 (where Counter performance was significantly improved).
you can use a dictionary to save the last position of the element and then build a new list with that information
>>> data=['1', '2', '3', '4', '1', '5']
>>> temp={ e:i for i,e in enumerate(data) }
>>> sorted(temp, key=lambda x:temp[x])
['2', '3', '4', '1', '5']
>>>

how to combine list of tuples based on common value into a list

I have a long list of tuples, could look like this for example:
[('5','9'), ('10','11'), ('1','2'), ('1','3'), ('1','4'), ('2','7'), ('3','8'), ('2','1'), ('3','1'), ('3','4'), ('5','6'), ('5','10'), ('10','12'), ('11','13'), ('13','14')]
I need to combine them into lists if they share anything in common. So the output in the example would be:
['11', '10', '13', '12', '14', '5', '6', '9']
['1', '3', '2', '4', '7', '8']
To clarify: the input is a list of tuples. I need to combine all tuples with shared element into one list. So if I will have: [('1','2'), ('1','3'), ('1','4'), ('4','5')], all the elements should all be put into one list ['1', '2', '3', '4', '5'], because they are linked through the tuples.
I tried to come up with something going through dictionaries byt failed miserably. I am sure there some "easier" solution.
thank you
Martin
Looks like you are doing union-find operations. https://en.wikipedia.org/wiki/Disjoint-set_data_structure
Start with creating singleton disjoint sets, each having a number occurring in your list. Next, for each tuple, union the sets corresponding to the numbers in the tuple.
The above solution will have running time nearly linear in the number of tuples. See A set union find algorithm for possible union-find implementations.
We can frame this problem as that of finding connected components in an undirected graph. All distinct numbers that appear in the list can be treated as the nodes (vertices) of the graph, and the pairs as its edges.
Here is a simple algorithm with inline comments:
l = [('5','9'), ('10','11'), ('1','2'), ('1','3'), ('1','4'), ('2','7'), ('3','8'), ('2','1'), ('3','1'), ('3','4'), ('5','6'), ('5','10'), ('10','12'), ('11','13'), ('13','14')]
# get all unique elements ("nodes") of `l'
nodes = set().union(*map(set, l))
# start with each node in its own connected component
comp = {node:{node} for node in nodes}
# now repeatedly merge pairs of components connected by edges in `l'
while True:
merged = False
new_l = [] # will drop edges that have already been used in a merge
for n1, n2 in l:
if comp[n1] is not comp[n2]:
# the two connected components are not the same, so merge them
new_comp = comp[n1] | comp[n2]
for n in new_comp:
comp[n] = new_comp
merged = True
else:
# keep the pair for the next iteration
new_l.append((n1, n2))
if not merged:
# all done
break
l = new_l
# now print all distinct connected components
for c in set(map(frozenset, comp.values())):
print list(c)
This prints out:
['1', '3', '2', '4', '7', '8']
['11', '10', '13', '12', '14', '5', '6', '9']

Remove odd-indexed elements from list in Python

I'm trying to remove the odd-indexed elements from my list (where zero is considered even) but removing them this way won't work because it throws off the index values.
lst = ['712490959', '2', '623726061', '2', '552157404', '2', '1285252944', '2', '1130181076', '2', '552157404', '3', '545600725', '0']
def remove_odd_elements(lst):
i=0
for element in lst:
if i % 2 == 0:
pass
else:
lst.remove(element)
i = i + 1
How can I iterate over my list and cleanly remove those odd-indexed elements?
You can delete all odd items in one go using a slice:
del lst[1::2]
Demo:
>>> lst = ['712490959', '2', '623726061', '2', '552157404', '2', '1285252944', '2', '1130181076', '2', '552157404', '3', '545600725', '0']
>>> del lst[1::2]
>>> lst
['712490959', '623726061', '552157404', '1285252944', '1130181076', '552157404', '545600725']
You cannot delete elements from a list while you iterate over it, because the list iterator doesn't adjust as you delete items. See Loop "Forgets" to Remove Some Items what happens when you try.
An alternative would be to build a new list object to replace the old, using a list comprehension with enumerate() providing the indices:
lst = [v for i, v in enumerate(lst) if i % 2 == 0]
This keeps the even elements, rather than remove the odd elements.
Since you want to eliminate odd items and keep the even ones , you can use a filter as follows :
>>>filtered_lst=list(filter(lambda x : x % 2 ==0 , lst))
this approach has the overhead of creating a new list.

I want a program that writes every possible combination to a different line of a text file

I want to write a program that would print every combination of a set of variables to a text file, creating a word list. Each answer should be written on a separate line and write all of the results for 1 digit, 2 digits, and 3 digits to a single text file.
Is there a simple way I can write a python program that can accomplish this? Here is an example of the output I am expecting when printing all the binary number combinations possible for 1, 2, and 3 digits:
Output:
0
1
00
01
10
11
000
001
010
011
100
101
110
111
A naïve solution which solves the problem and is general enough for any application you might have is this:
def combinations(words, length):
if length == 0:
return []
result = [[word] for word in words]
while length > 1:
new_result = []
for combo in result:
new_result.extend(combo + [word] for word in words)
result = new_result[:]
length -= 1
return result
Basically, this gradually builds up a tree in memory of all the combinations, and then returns them. It is memory-intensive, however, and so is impractical for large-scale combinations.
Another solution for the problem is, indeed, to use counting, but then to transform the numbers generated into a list of words from the wordlist. To do so, we first need a function (called number_to_list()):
def number_to_list(number, words):
list_out = []
while number:
list_out = [number % len(words)] + list_out
number = number // len(words)
return [words[n] for n in list_out]
This is, in fact, a system for converting decimal numbers to other bases. We then write the counting function; this is relatively simple, and will make up the core of the application:
def combinations(words, length):
numbers = xrange(len(words)**length)
for number in numbers:
combo = number_to_list(number, words)
if len(combo) < length:
combo = [words[0]] * (length - len(combo)) + combo
yield combo
This is a Python generator; making it a generator allows it to use up less RAM. There is a little work to be done after turning the number into a list of words; this is because these lists will need padding so that they are at the requested length. It would be used like this:
>>> list(combinations('01', 3))
[['0', '0', '0'], ['0', '0', '1'],
['0', '1', '0'], ['0', '1', '1'],
['1', '0', '0'], ['1', '0', '1'],
['1', '1', '0'], ['1', '1', '1']]
As you can see, you get back a list of lists. Each of these sub-lists contains a sequence of the original words; you might then do something like map(''.join, list(combinations('01', 3))) to retrieve the following result:
['000', '001', '010', '011', '100', '101', '110', '111']
You could then write this to disk; a better idea, however, would be to use the built-in optimizations that generators have and do something like this:
fileout = open('filename.txt', 'w')
fileout.writelines(
''.join(combo) for combo in combinations('01', 3))
fileout.close()
This will only use as much RAM as necessary (enough to store one combination). I hope this helps.
# Given two lists of strings, return a list of all ways to concatenate
# one from each.
def combos(xs, ys):
return [x + y for x in xs for y in ys]
digits = ['0', '1']
for c in combos(digits, combos(digits, digits)):
print c
#. 000
#. 001
#. 010
#. 011
#. 100
#. 101
#. 110
#. 111
It shouldn't be too hard in most languages. Does the following pseudo-code help?
for(int i=0; i < 2^digits; i++)
{
WriteLine(ToBinaryString(i));
}
A basic function to produce all the permutations of a list is given below. In this approach, permutations are created lazily by using generators.
def perms(seq):
if seq == []:
yield []
else:
res = []
for index,item in enumerate(seq):
rest = seq[:index] + seq[index+1:]
for restperm in perms(rest):
yield [item] + restperm
alist = [1,1,0]
for permuation in perms(alist):
print permuation

Categories