How to continue for loop until it meets condition? [closed] - python

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 2 years ago.
Improve this question
I want to looping until it meets the condition. In this case i want to continue till List_list looks like
["one","one","two","two","three","three","four","four","five","five","six","seven","eight","nine","ten"]
lst =["one","two","three","four","five","six","seven","eight","nine","ten”]
List_list = list()
for rn in lst:
List_list.append(rn)
if 15 == len(List_list):
break

Ask #2:
Solution to repeat first 5 items, then single instance of next 5 items
lst =["one","two","three","four","five","six","seven","eight","nine","ten"]
List_list = []
for i in range(10):
List_list.append(lst[i])
if i < 5:
List_list.append(lst[i])
print (List_list)
The output of this will be:
['one', 'one', 'two', 'two', 'three', 'three', 'four', 'four', 'five', 'five', 'six', 'seven', 'eight', 'nine', 'ten']
If you are looking for a single line answer using list comprehension, then you can use this.
List_list = [y for x in lst[:5] for y in [x,x]] + [x for x in lst[5:]]
print (List_list)
Output is the same:
['one', 'one', 'two', 'two', 'three', 'three', 'four', 'four', 'five', 'five', 'six', 'seven', 'eight', 'nine', 'ten']
Ask #1:
Solution for earlier question: Add 15 items to a list: All 10 items from original list + first from original list
You can do something as simple as this:
List_lst = lst + lst[:5]
print (List_lst)
If you still insist on using a for loop and you want 15 items, then do this and it will give you same output.
List_list = list()
for i in range(15):
List_list.append(lst[i%10])
print (List_list)
A list comprehension version of this will be:
List_list = [lst[i%10] for i in range(15)]
print (List_list)
If you want to fix your code with a while loop, see the details below.
Convert the for loop to while True:. Start iterating using a counter i and check for mod of 10 to get the position to be inserted.
lst = ["one", "two", "three", "four", "five", "six", "seven", "eight", "nine", "ten"]
List_list = list()
i = 0
while True:
List_list.append(lst[i%10])
i+=1
if len(List_list) == 15:
break
print (List_list)
This will result in
["one", "two", "three", "four", "five", "six", "seven", "eight", "nine", "ten", "one", "two", "three", "four", "five"]

This seems like a simple modulo 10 loop...
lst =["01.one","02.two","03.three","04.four","05.five","06.six","07.seven","08.eight","09.nine","10.ten"]
[w[3:] for w in sorted([lst[n%10] for n in range(15)])]
output
['one', 'one', 'two', 'two', 'three', 'three', 'four', 'four', 'five', 'five', 'six', 'seven', 'eight', 'nine', 'ten']

["one","two","three","four","five","six","seven","eight","nine","ten","one","two","three","four","five"]
lst =["one","two","three","four","five","six","seven","eight","nine","ten"]
List_list = []
length = 0
# Respect the looping statement
while length<15:
List_list.append(lst[length%10])
length+=1
print(List_list)
#Output ['one', 'two', 'three', 'four', 'five', 'six', 'seven', 'eight', 'nine', 'ten', 'one', 'two', 'three', 'four', 'five']

EDIT 2: Complemented the answer for the updated question.
Using itertools from Python Standard Library, you can do it in three steps (steps 1 and 2 can be combined):
Use the cycle function to create an infinite iterator of the original list.
Use the islice function to get the first 15 elements from the infinite iterator.
Sort items in the resultant list by the position in the original list.
from itertools import cycle, islice
lst = ["one","two","three","four","five","six","seven","eight","nine","ten"]
infinite_lst = cycle(lst)
List_list = list(islice(infinite_lst, 15))
List_list.sort(key=lst.index)
print(List_list)
And here you have:
['one', 'one', 'two', 'two', 'three', 'three', 'four', 'four', 'five', 'five', 'six', 'seven', 'eight', 'nine', 'ten']

Use itertools.cycle:
from itertools import cycle
lst = {
"one": 1,
"two": 2,
"three": 3,
"four": 4,
"five": 5,
"six": 6,
"seven": 7,
"eight": 8,
"nine": 9,
"ten": 10
}
def get_lst(times):
output = []
for item in cycle(lst):
output.append(item)
if len(output) >= times:
break
return sorted(output, key=lambda i: lst[i])
print(get_lst(10))
-> ['one', 'two', 'three', 'four', 'five', 'six', 'seven', 'eight', 'nine', 'ten']
print(get_lst(11))
-> ['one', 'one', 'two', 'three', 'four', 'five', 'six', 'seven', 'eight', 'nine', 'ten']

I agree that the second code in this answer is not more complicated as it is much easier to replicate for any other code. The best programmers create code which can be reproduced in any circumstance the best.

Related

How to filter list items based on regex in python?

I have two list items and I want to generate a list based on non-matching items. Here is what I am trying to do:
from __future__ import print_function
import os
mainline_list = ['one', 'two', 'three', 'four']
non_main_list = ['two', 'seven', 'six', 'four', 'four-3.1', 'new_three']
itemized_list = [item for item in non_main_list if item not in mainline_list]
print(itemized_list)
What is returns is
['seven', 'six', 'four-3.1', 'new_three']
while what I want is:
['seven', 'six']
Regex is not necessary, you can use all() builtin function:
mainline_list = ['one', 'two', 'three', 'four']
non_main_list = ['two', 'seven', 'six', 'four', 'four-3.1', 'new_three']
print([item for item in non_main_list if all(i not in item for i in mainline_list)])
Prints:
['seven', 'six']

Python list rearrange the elements in a required order

My main list has 44 names as elements. I want to rearrange them in a specific order. I am giving here an example. Note that elements in my actual list are some technical names. No way related to what I have given here.
main_list = ['one','two','five','six',.................'twentyone','three','four','seven','eight',.....,'fortyfour']
I want to rearrange the list. I have no idea how to proceed. But my expected output should like this
Expected output:
main_list = ['one','two','three','four','five','six','seven','eight'.................'twentyone',,.....,'fortyfour']
You can have a dictionary to use as your sorting key:
sort_keys = {
'one': 1,
'two': 2,
'three': 3,
'ten': 10,
'twenty': 20,
}
main_list = ['twenty', 'one', 'three', 'ten', 'two']
main_list.sort(key=lambda i: sort_keys[i])
print(main_list)
Output:
['one', 'two', 'three', 'ten', 'twenty']
Use something like this (this is just the first Google hit I found for something to convert English representations of numbers to integer values; whatever you use needs to be something that works to convert whatever your actual data is into something sortable): https://pypi.org/project/word2number/
from word2number import w2n
main_list.sort(key=w2n.word_to_num)
Or come up with your own cheesy version as appropriate to your data. Taking your example you could do something like:
number_words = {
'one': 1,
'two': 2,
'three': 3,
'four': 4,
'five': 5,
'six': 6,
'seven': 7,
'eight': 8,
'twenty': 20,
'forty': 40,
'sixty': 60,
}
def word_to_number(word: str) -> int:
if word in number_words:
return number_words[word]
# Try chomping each number out of the word.
for n in number_words:
if word.endswith(n):
return number_words[n] + word_to_number(word[:-len(n)])
raise ValueError(f"I don't know what number '{word}' is!")
>>> main_list
['one', 'two', 'sixtyfour', 'five', 'six', 'twentyone', 'three', 'four', 'seven', 'eight', 'fortyfour']
>>> sorted(main_list, key=word_to_number)
['one', 'two', 'three', 'four', 'five', 'six', 'seven', 'eight', 'twentyone', 'fortyfour', 'sixtyfour']
It looks like you want to sort number words in numeric order. But your examples above have poorly-formed words that need fixing, such as twentyone and fortyfour. This is one way you could address it.
from word2number import w2n
main_list = ['one', 'two', 'five', 'six', 'twentyone', 'three', 'four', 'seven', 'eight', 'fortyfour']
VALID = ['zero', 'one', 'two', 'three', 'four', 'five', 'six', 'seven', 'eight', 'nine', 'ten', 'eleven', 'twelve', 'thirteen', 'fourteen', 'fifteen', 'sixteen', 'seventeen', 'eighteen', 'nineteen']
TENS = ['twenty', 'thirty', 'forty', 'fifty', 'sixty', 'seventy', 'eighty', 'ninety']
renamed = []
for item in main_list:
if item in VALID or item in TENS:
renamed.append(w2n.word_to_num(item))
else:
for num in TENS:
one = item.split(num)[-1]
if one in VALID:
renamed.append(w2n.word_to_num(f'{num} {one}'))
Output
>>>sorted(renamed)
[1, 2, 3, 4, 5, 6, 7, 8, 21, 44]

lambda in lambda

Can anybody explain me whats wrong i am doing here -
multiArray = [
['one', 'two', 'three', 'four', 'five'],
['one', 'two', 'three', 'four', 'five'],
['one', 'two', 'three', 'four', 'five']
]
search ='four'
p1 = list(filter(lambda outerEle: search == outerEle, multiArray[0]))
p = list(filter(lambda multiArrayEle: list(filter(lambda innerArrayEle: search == innerArrayEle, multiArrayEle)), multiArray))
print (p1)
print (p)
The result i am getting here is
['four']
[['one', 'two', 'three', 'four', 'five'], ['one', 'two', 'three', 'four', 'five'], ['one', 'two', 'three', 'four', 'five']]
while i am expecting
[['four'],['four'],['four']]
In your second filter, you are using a list as a predicate (as opposed to simply a bool as you do in the first filter); now, this implicitly applies the built-in method bool to each element list, and for a list l, bool(l) is true exactly when l is non-empty:
In [4]: bool([])
Out[4]: False
In [5]: bool(['a'])
Out[5]: True
This allows you to pick out, for example, all the non-empty lists in a list of lists:
In [6]: ls = [['a'], [], ['b']]
In [7]: list(filter(lambda l: l, ls))
Out[7]: [['a'], ['b']]
Thus, in your case, at the end of the day, your filter ends up giving you all lists for which 'four' appears, which is all of them.
From your given example, it's not immediately obvious what you are trying to achieve as all the inputs are identical, but my guess is that it's something like the following:
In [19]: multiArray = [
...: ['one', 'two', 'three', 'four', 'five', 'four'],
...: ['one', 'two', 'three', 'for', 'five'],
...: ['one', 'two', 'three', 'four', 'five']
...: ]
In [20]: [list(filter(lambda x: x == search, l)) for l in multiArray]
Out[20]: [['four', 'four'], [], ['four']]
While #fuglede's answer is really the answer to your question, you can archive the result you want by changing your outer filter to map:
p = list(map(lambda multiArrayEle: list(filter(lambda innerArrayEle: search == innerArrayEle, multiArrayEle)), multiArray))

Remove percentage of items in a list randomly

I have one list of n elements. Now I have to remove a percentage of all the elements in this list. The removed elements have to be all randomly picked.
For example, let n = 0,2 (20% to be deleted)
n = 0.2
list = [one, two, three, four, five, six, seven, eight, nine, ten]
After the randomly removed 20%, the list will be:
list = [one, three, four, five, seven, eight, nine, ten] # two and seven deleted
Now you probably think, mmm this isn't that hard... Well it all has to be done in one line and I am kinda new to those oneliners...
So a new function has to be made which returns the same list but without a percentage of the elements:
def remove(n, list):
return list # But the new list with elements removed
Please help, what to type behind the return?
you could use random.sample to pick (100*(1-n))% items:
import random
def remove(l,n):
return random.sample(l,int(len(l)*(1-n)))
print(remove(list(range(1,11)),0.2))
result:
[10, 8, 4, 7, 1, 9, 6, 2]
beware of float to integer rounding though, you may throw in a int(len(l)*(1-n)+0.5) to avoid truncation and get nearest instead.
EDIT: another approach would be to pop the computed number of items at random indexes (recomputing the len of the list each time is simpler, to avoid index out of bounds):
def remove(l,n):
for _ in range(int(len(l)*n)):
l.pop(random.randrange(0,len(l)))
return l
not a list comprehension, not one-liner, but works in-place. Maybe faster when the percentage of items to remove is low.
You can try this:
import random
list = ["one", "two", "three", "four", "five", "six", "seven", "eight", "nine", "ten"]
new_list = [b for b in list if b not in [random.choice(list) for i in range(int(len(list)*0.2))]]
Output:
['one', 'three', 'four', 'six', 'seven', 'eight', 'nine', 'ten']
depends on whether the 'one line' has to be after the return, this list comprehension uses lst.pop(i) to remove the items at the randomly generated fraction of indcies i in one line, sorting indices in reverse to pop last to first avoiding possible index out of range error
lst = ["one", "two", "three", "four", "five", "six", "seven", "eight", "nine", "ten"]
def remove(n, lst):
[lst.pop(i) for i in sorted(random.sample(range(len(lst)), k=int(len(lst)*n)),
reverse=True)]
return lst
remove(0.2, lst)
Out[37]: ['one', 'two', 'three', 'four', 'seven', 'eight', 'nine', 'ten']
and we modified lst itself:
lst
Out[38]: ['one', 'two', 'three', 'four', 'seven', 'eight', 'nine', 'ten']
refresh lst:
lst = ["one", "two", "three", "four", "five", "six", "seven", "eight", "nine", "ten"]
and feed remove() a copy of lst
remove(0.2, lst[:])
Out[40]: ['one', 'two', 'three', 'four', 'six', 'eight', 'nine', 'ten']
and the original list is presrved:
lst
Out[41]: ['one', 'two', 'three', 'four', 'five', 'six', 'seven', 'eight', 'nine', 'ten']
if the problem really, really specifies only a line of code, inline with the return then you could abuse the inline if-else:
def remove(n, lst):
return lst if [lst.pop(i)
for i in sorted(random.sample(range(len(lst)),
k=int(len(lst)*n)),
reverse=True)] else lst

Python - Unique Lists [closed]

Closed. This question does not meet Stack Overflow guidelines. It is not currently accepting answers.
Questions asking for code must demonstrate a minimal understanding of the problem being solved. Include attempted solutions, why they didn't work, and the expected results. See also: Stack Overflow question checklist
Closed 9 years ago.
Improve this question
I have a list of lists. I want to get all unique lists based on just the first three elements. If there are duplicates, then it should just return the last item. So for instance based on this
[['one', 'two', 'three', 'teennn'], ['five', 'five', 'five', 'five'],
['seven', 'nine', 'ten', 'eleven'], ['one', 'two', 'three', 'four']]
I want to return this
[['five', 'five', 'five', 'five'],
['seven', 'nine', 'ten', 'eleven'], ['one', 'two', 'three', 'four']]
lst = [['one', 'two', 'three', 'teennn'],
['five', 'five', 'five', 'five'],
['seven', 'nine', 'ten', 'eleven'],
['one', 'two', 'three', 'four']]
output = []
seen = set()
lst.reverse()
for item in lst:
if not item[:3] in seen:
output.append(item)
seen.add(item[:3])
output.reverse()
This ensures that the first three items are always unique. Starting from the end of your list lst, using reverse, ensures that the last appearance of each starting set is included.
If order isn't important, then you can use a dict:
data = [['one', 'two', 'three', 'teennn'], ['five', 'five', 'five', 'five'], ['seven', 'nine', 'ten', 'eleven'], ['one', 'two', 'three', 'four']]
new = {tuple(el[:3]): el for el in data}.values()
# [['one', 'two', 'three', 'four'], ['seven', 'nine', 'ten', 'eleven'], ['five', 'five', 'five', 'five']]
Or, if you really wanted to maintain order, then something like:
new = [data[idx] for idx in sorted({tuple(el[:3]): idx for idx, el in enumerate(data)}.values())]

Categories