How to write a function that does the following -
After each occurrence of num1 in a list, insert num2
def insert_after(lst, num1, num2):
In general, people on stack overflow would appreciate you to at least attempt a solution before asking for help. That being said, here is an O(1) solution that is the first to come to mind:
PREVIOUS ANSWER WAS INCORRECT
The best way to do this is as follow:
Iterating through the length of the list as I did before does not work, as the list is growing when you insert but you are iterating through a fixed number.
def insert_after(lst,num1,num2):
output = []
for num in lst:
output.append(num)
if num == num1:
output.append(num2)
return output
Here are a couple fun ways using list comprehensions:
Solution 1:
lst = [1,5,4,3,5,5,7,8,9,6,5]
def insert_after_more_readable(lst,num1,num2):
temp_lst = [[num] if num != num1 else [num, num2] for num in lst]
final_lst = [elem for sublist in temp_lst for elem in sublist]
return final_lst
print(lst, 5,8)
Explanation:
We create a list of lists called temp_lst. Every time we encounter num1, we insert a sublist [num1,num2], and otherwise we insert sublist [num].
We iterate over all the sublists, and take out all their elements and put them into the outer list.
Solution 2:
This is a less readable version, but the exact same thing using nested list comprehensions, all in one line.
lst = [1,5,4,3,5,5,7,8,9,6,5]
def insert_after(lst, num1, num2):
return [elem for sublist in [[num] if num != num1 else [num,num2]
for num in lst] for elem in sublist]
print(lst, 5,8)
In this version, the inner list that is formed is equivalent to temp_lst above.
Related
I have a list of numbers and I want to check if a definite sequence exists in that list. For example, for [1,1,2,2,3,3,3,4,5,5,6] how can I determine if the sequence 3-4-5 exists?
I tried using nested loops, but ran into a problem with break/continue. I am now reducing the list to its unique elements and seeing if my sequence exists:
ls = [1,1,2,2,3,3,3,4,5,5,6]
uniq_ls = []
for item in ls:
if item not in uniql:
uniq_ls.append(item)
for ii, item in enumerate(uniq_ls):
if item == 3:
if uniq_ls[ii+1] == 4:
if uniq_ls[ii+2] == 5:
print('yes, sequence exists')
Above method works, but I want to do this without reducing the original list to its unique elements.
How can I do this?
As pointed out by some folks, this method will work only if the original list is sorted.
It will not work for a list like [1,1,1,3,2,2,4,3,3,4,4,4,4,5,3,2,1]
I need it to work for a unsorted list like this one.
You can use this function:
def f(lst, seq):
for n in range(len(lst)-len(seq)+1):
if lst[n:n+len(seq)] == seq:
return True
return False
print(f([1,1,2,2,3,3,3,4,5,5,6], [3,4,5]))
Output:
True
You can also turn that into a one-liner:
def f(lst, seq):
return any(lst[n:n+len(seq)] == seq for n in range(len(lst)-len(seq)+1))
I worked out a solution to this when the list is unsorted. I am not sure if this is the most elegant, pythonic way -
List L1 is [1,1,1,3,2,2,4,3,3,4,4,4,4,5,3,2,1]
I will have an empty list L2 = [] and add first item of list to it.
Then I will append L2 with item from L1 if previous item is not the same as current item
So L2 eventually should look like [1,3,2,4,3,4,5,3,2,1]
From this list it will be easy to find a sequence 3-4-5.
New code:
l1 = [1,3,2,4,3,4,5,3,2,1]
l_uni = []
for ii, item in enumerate(l1):
if ii==0:
l_uni.append(item)
elif l1[ii] != l1[ii-1]:
l_uni.append(item)
for jj in range(0,len(l_uni)):
try:
if l_uni[jj] == 3:
if l_uni[jj+1] == 4:
if l_uni[jj+2] == 5:
print('found sequence')
break
except IndexError:
print('no sequence')
I want to square every number in an input integer but when I try to do it my code returns list of original integers, not integers squared, why?
def square_digits(num):
lst = [int(x) for x in str(num)]
for digit in lst :
digit == digit **2
return lst
The variable digit within the for loop is a copy of the value within the list, not a reference to it. Modifying that value does not modify the list. (Also, as others have pointed out, you need the = operator to modify a value, not ==!)
Here are two different ways you could accomplish what you're after:
Using an enumeration to modify lst in your loop:
def square_digits(num):
lst = [int(x) for x in str(num)]
for i, digit in enumerate(lst):
lst[i] = digit **2
return lst
or using comprehension to build and return the list of squares:
def square_digits(num):
return [int(x)**2 for x in str(num)]
2 reasons:
You are using == which is for checking equality instead of = which is for assigning value.
Even if you were using = you are not updating that list.
The code below should work better
def square_digits(num):
lst = [int(x) for x in str(num)]
newList = [digit ** 2 for digit in lst]
return newList
Because you are returning a lst.
def square(num):
lst = [int(x)**2 for x in num]
return lst
Given that l = [[1,2,3], [3,4,5],[5,6]], is there a method to return a list that consists of all positions of 3 within l; i.e. return [2,3]. A sample code I wrote is:
def pos_in_lists(seq, elem):
while i < len(seq):
elem_pos = seq[i].index(elem)
return [elem_pos]
When I run this, it only returns 2, which is not the result I want. What is my mistake? Also, is there a more simple way to solve my problem?
Your code only returns a list with one element (return [elem_pos]). You need to have a list variable (result) outside the loop to keep track of the result of previous lists by appending to that list.
def pos_in_lists(seq, elem):
result = []
i = 0
while i < len(seq):
if elem in seq[i]:
elem_pos = seq[i].index(elem)
result.append(elem_pos)
i += 1
return result
Another simpler alternative is to use list comprehension
def pos_in_lists(seq, elem):
return [l.index(elem) for l in seq if elem in l]
You need to increment "i" each loop
"return" forces the loop to exit. That should be outside the loop at the end of the code.
According to my understanding of the problem, Given list l = [[1,2,3], [3,4,5],[5,6]] and if we have to find 3, the output list should be [2,0].
Following mistakes are there in the code provided:
The code is not working as i is not defined in your method before using it.
We need to store positions of all 3 value present in the list, thus we need to have a list in which we store all the positions of 3 that we can find in the list. You have returned the result as soon as you have found one value. Thus, you are getting only 2.
seq[i].index(elem) will throw value error if 3 is not in the list.
Solution
def pos_in_lists(seq, elem):
res = []
for innerList in seq:
if elem in innerList:
res.append(innerList.index(elem))
return res
pos_in_lists(l,3)
Result would be [2,0]
we can use list comprehension as well:
def pos_in_lists(seq, elem):
return [innerList.index(elem) for innerList in seq if elem in innerList]
I need to write a code where a function takes in a list and then returns the longest string from that list.
So far I have:
def longestword(alist):
a = 0
answer = ''
for i in alist:
x = i
if x > a:
a = x
answer = x
elif i == a:
if i not in alist:
answer = answer + ' ' + i
return answer
The example I have is longestword([11.22,"hello",20000,"Thanksgiving!",True])
which is supposed to return 'Thanksgiving!' but my function always returns True.
For starters, this always assigns x to the very last value in the list, which in your example is True.
for i in alist:
x = i
And you should try not to access a loop value outside of the loop because, again, it's the last value of the thing you looped over, so True
elif i == a:
The key to solving the problem is to pick out which values are strings (using isinstance()) and tracking the longest length ones (using the len() function)
def longeststring(lst):
longest = ""
for x in lst:
if isinstance(x, str) and len(x) > len(longest):
longest = x
return longest
Do be mindful of equal length strings. I don't know the requirements of your assignment.
I prefer to keep the for loops to a minimum; here's how I find the longest string in a list:
listo = ["long word 1 ", " super OMG long worrdddddddddddddddddddddd", "shortword" ]
lenList = []
for x in listo:
lenList.append(len(x))
length = max(lenList)
print("Longest string is: {} at {} characters.".format(listo[lenList.index(length)] , length))
Why not use...
str_list = [x for x in alist if isinstance(x, str)]
longestword = sorted(str_list, key=len, reverse=True)[0]
Using a list comprehension, create new_list by iterating the elements of your original list and retaining only the strings with.
And then your list will be sorted by the sorted() function.
Applying the key=len argument, your list will be sorted by the length of the list element using the built-in-function len().
And with the reverse=True argument, your list will be returned sorted in descending order, i.e. longest first.
Then you select index [0] of the sorted list which in this case, is the longest string.
To complete then:
def longestword(alist):
str_list = [x for x in alist if isinstance(x, str)]
longestword = sorted(str_list, key=len, reverse=True)[0]
return longestword
As Gavin rightly points out below, the sorting could be achieved without having to pass the reverse=True argument by returning the last element in the list with [-1], i.e.:
longestword = sorted(str_list, key=len)[-1]
You can try something like this :
def longest_string(some_list):
only_str = [s for s in some_list if isinstance(s, str)]
return max(only_str, key=len)
This method will create a list of strings named only_str. Then it will return the max length string using max() function.
When we run the longest_string() method with the example provided in the question:
some_list = [11.22,"hello",20000,"Thanksgiving!",True]
longest_string(some_list)
The output is: 'Thanksgiving!'
Hope this solves this problem!!
I'm stuck on this question for checking odd numbers, with for loop method
I've been given part of this code to produce odd numbers only
def get_odds(items):
new_list = []
return new_list
If anyone can help, that would be great - thanks!
You can use a list comprehension:
def get_odds(items):
new_list = [item for item in items if item % 2 == 1]
return new_list
Edit: If you have to use a for loop, you can write something in the lines of:
def get_odds(items):
new_list = []
for item in items:
if item % 2 == 1:
new_list.append(item)
return new_list
As you will see, this is just a longer way of writing the first solution.
How about
for a in range(10000):
if a%2==1:
new_list.append(a)
I am sure there are better algorithms but it is early and I have not had an coffee yet :)
def get_odds(items):
new_list = [] ###create an empty container to store odd no.s when passed into it
for item in items: ### loop over your items (a list probably)
if item%2 != 0: ####here u will get odd numbers(Yes ==1 also works)
new_list.append(item)
return new_list
Note: though List comprehension are more pythonic way, but a for loop is easy to understand logic.
l = lambda(y) : [i for i in xrange(y) if i%2!=0]
print l(1000)
Or simply
odd_list = [i for i in xrange(1000) if i%2!=0]