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!!
Related
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
program input is a string. From this string I would want the most common letter. In the case that there are multiple letters with the same frequency, I would return the one that comes first in the latin alphabet
code:
def most_Wanted(text="Hello Oman"):
lst = [x for x in text.replace(" ","").lower() if x.isalpha]
count = {}
for letter in lst:
if letter in count:
count[letter] += 1
else:
count[letter] = 1
count = list(count.items())
sorted(count, key=lambda x: (-x[1],x[0]))
print(count[0][0])
expected:
l #though o and l appear 3 times, l is before o in the latin alphabet
output:
h #there seems to be an error in the sorting as the first pair of tuples in the list always seems to be the first letter of the text?
Any suggestions to spruce up the code would be fine, though I would prefer not using modules at the moment so I can learn the core python. Thank you:)
The main issue is that sorted returns a new list, it is not in-place.
You should either reassign its return value, or use .sort():
count = sorted(count, key=lambda x: (-x[1],x[0]))
or
count.sort(key=lambda x: (-x[1],x[0]))
There is also an issue in the line
lst = [x for x in text.replace(" ","").lower() if x.isalpha]
if x.isalpha is always going to return True since it is only referencing the function instead of actually calling it. It should be changed to
lst = [x for x in text.replace(" ","").lower() if x.isalpha()]
I am trying to write a function which consumes a string and a character and produces a list of indices for all occurrences of that character in that string.
So far this is what I have, but it always gives me [].
def list_of_indices(s,char):
string_lowercase = s.lower()
sorted_string = "".join(sorted(string_lowercase))
char_list = list(sorted_string)
for x in char_list:
a = []
if x == char:
a.append(char_list.index(x))
return a
I don't understand why this does not yield the answer. And it has to be a list of non-empty length.
Anyone aware of how to get the indices for all occurrences?
You're returning on the first iteration of your for-loop. Make sure the return statement is outside the scope of the loop.
Also, be sure to put a = [] before the for-loop. Otherwise, you're effectively resetting the list on each iteration of loop.
There is also a problem with char_list.index(x). This will always return the index of the first occurrence of x, which isn't what you want. You should keep track of an index as you are looping (e.g. with enumerate()).
And I'm not sure what you were trying to do with the sort; looping through the original string should be sufficient.
Lastly, note that you can loop over a string directly; you don't need to convert it to a list (i.e. char_list is unnecessary).
Note that your task can be accomplished with a simple list comprehension:
>>> s = 'abcaba'
>>> char = 'a'
>>>
>>> [i for i,c in enumerate(s) if c == char] # <--
[0, 3, 5]
You could implement it using a quick list comprehension.
def list_of_indicies(s, char):
return [i for i, c in enumerate(s) if c == char]
or by using a for loop instead:
def list_of_indicies(s, char):
results = list()
for i, c in enumerate(s):
if c == char:
results.append(i)
return results
You are returning a on the first loop of your for loop iteration.
Change for loop to this for starters:
def list_of_indices(s,char):
string_lowercase = s.lower()
a = []
i = 0
for x in string_lowercase:
if x == char:
a.append(i)
i+=1
return a
I have a set of strings, e.g.
my_prefix_what_ever
my_prefix_what_so_ever
my_prefix_doesnt_matter
I simply want to find the longest common portion of these strings, here the prefix. In the above the result should be
my_prefix_
The strings
my_prefix_what_ever
my_prefix_what_so_ever
my_doesnt_matter
should result in the prefix
my_
Is there a relatively painless way in Python to determine the prefix (without having to iterate over each character manually)?
PS: I'm using Python 2.6.3.
Never rewrite what is provided to you: os.path.commonprefix does exactly this:
Return the longest path prefix (taken
character-by-character) that is a prefix of all paths in list. If list
is empty, return the empty string (''). Note that this may return
invalid paths because it works a character at a time.
For comparison to the other answers, here's the code:
# Return the longest prefix of all list elements.
def commonprefix(m):
"Given a list of pathnames, returns the longest common leading component"
if not m: return ''
s1 = min(m)
s2 = max(m)
for i, c in enumerate(s1):
if c != s2[i]:
return s1[:i]
return s1
Ned Batchelder is probably right. But for the fun of it, here's a more efficient version of phimuemue's answer using itertools.
import itertools
strings = ['my_prefix_what_ever',
'my_prefix_what_so_ever',
'my_prefix_doesnt_matter']
def all_same(x):
return all(x[0] == y for y in x)
char_tuples = itertools.izip(*strings)
prefix_tuples = itertools.takewhile(all_same, char_tuples)
''.join(x[0] for x in prefix_tuples)
As an affront to readability, here's a one-line version :)
>>> from itertools import takewhile, izip
>>> ''.join(c[0] for c in takewhile(lambda x: all(x[0] == y for y in x), izip(*strings)))
'my_prefix_'
Here's my solution:
a = ["my_prefix_what_ever", "my_prefix_what_so_ever", "my_prefix_doesnt_matter"]
prefix_len = len(a[0])
for x in a[1 : ]:
prefix_len = min(prefix_len, len(x))
while not x.startswith(a[0][ : prefix_len]):
prefix_len -= 1
prefix = a[0][ : prefix_len]
The following is an working, but probably quite inefficient solution.
a = ["my_prefix_what_ever", "my_prefix_what_so_ever", "my_prefix_doesnt_matter"]
b = zip(*a)
c = [x[0] for x in b if x==(x[0],)*len(x)]
result = "".join(c)
For small sets of strings, the above is no problem at all. But for larger sets, I personally would code another, manual solution that checks each character one after another and stops when there are differences.
Algorithmically, this yields the same procedure, however, one might be able to avoid constructing the list c.
Just out of curiosity I figured out yet another way to do this:
def common_prefix(strings):
if len(strings) == 1:#rule out trivial case
return strings[0]
prefix = strings[0]
for string in strings[1:]:
while string[:len(prefix)] != prefix and prefix:
prefix = prefix[:len(prefix)-1]
if not prefix:
break
return prefix
strings = ["my_prefix_what_ever","my_prefix_what_so_ever","my_prefix_doesnt_matter"]
print common_prefix(strings)
#Prints "my_prefix_"
As Ned pointed out it's probably better to use os.path.commonprefix, which is a pretty elegant function.
The second line of this employs the reduce function on each character in the input strings. It returns a list of N+1 elements where N is length of the shortest input string.
Each element in lot is either (a) the input character, if all input strings match at that position, or (b) None. lot.index(None) is the position of the first None in lot: the length of the common prefix. out is that common prefix.
val = ["axc", "abc", "abc"]
lot = [reduce(lambda a, b: a if a == b else None, x) for x in zip(*val)] + [None]
out = val[0][:lot.index(None)]
Here's a simple clean solution. The idea is to use zip() function to line up all the characters by putting them in a list of 1st characters, list of 2nd characters,...list of nth characters. Then iterate each list to check if they contain only 1 value.
a = ["my_prefix_what_ever", "my_prefix_what_so_ever", "my_prefix_doesnt_matter"]
list = [all(x[i] == x[i+1] for i in range(len(x)-1)) for x in zip(*a)]
print a[0][:list.index(0) if list.count(0) > 0 else len(list)]
output: my_prefix_
Here is another way of doing this using OrderedDict with minimal code.
import collections
import itertools
def commonprefix(instrings):
""" Common prefix of a list of input strings using OrderedDict """
d = collections.OrderedDict()
for instring in instrings:
for idx,char in enumerate(instring):
# Make sure index is added into key
d[(char, idx)] = d.get((char,idx), 0) + 1
# Return prefix of keys while value == length(instrings)
return ''.join([k[0] for k in itertools.takewhile(lambda x: d[x] == len(instrings), d)])
I had a slight variation of the problem and google sends me here, so I think it will be useful to document:
I have a list like:
my_prefix_what_ever
my_prefix_what_so_ever
my_prefix_doesnt_matter
some_noise
some_other_noise
So I would expect my_prefix to be returned. That can be done with:
from collections import Counter
def get_longest_common_prefix(values, min_length):
substrings = [value[0: i-1] for value in values for i in range(min_length, len(value))]
counter = Counter(substrings)
# remove count of 1
counter -= Counter(set(substrings))
return max(counter, key=len)
In one line without using itertools, for no particular reason, although it does iterate through each character:
''.join([z[0] for z in zip(*(list(s) for s in strings)) if all(x==z[0] for x in z)])
Find the common prefix in all words from the given input string, if there is no common prefix print -1
stringList = ['my_prefix_what_ever', 'my_prefix_what_so_ever', 'my_prefix_doesnt_matter']
len2 = len( stringList )
if len2 != 0:
# let shortest word is prefix
prefix = min( stringList )
for i in range( len2 ):
word = stringList[ i ]
len1 = len( prefix )
# slicing each word as lenght of prefix
word = word[ 0:len1 ]
for j in range( len1 ):
# comparing each letter of word and prefix
if word[ j ] != prefix[ j ]:
# if letter does not match slice the prefix
prefix = prefix[ :j ]
break # after getting comman prefix move to next word
if len( prefix ) != 0:
print("common prefix: ",prefix)
else:
print("-1")
else:
print("string List is empty")
I have a list of variable length and am trying to find a way to test if the list item currently being evaluated is the longest string contained in the list. And I am using Python 2.6.1
For example:
mylist = ['abc','abcdef','abcd']
for each in mylist:
if condition1:
do_something()
elif ___________________: #else if each is the longest string contained in mylist:
do_something_else()
Surely there's a simple list comprehension that's short and elegant that I'm overlooking?
From the Python documentation itself, you can use max:
>>> mylist = ['123','123456','1234']
>>> print max(mylist, key=len)
123456
def longestWord(some_list):
count = 0 #You set the count to 0
for i in some_list: # Go through the whole list
if len(i) > count: #Checking for the longest word(string)
count = len(i)
word = i
return ("the longest string is " + word)
or much easier:
max(some_list , key = len)
What should happen if there are more than 1 longest string (think '12', and '01')?
Try that to get the longest element
max_length,longest_element = max([(len(x),x) for x in ('a','b','aa')])
And then regular foreach
for st in mylist:
if len(st)==max_length:...
To get the smallest or largest item in a list, use the built-in min and max functions:
lo = min(L)
hi = max(L)
As with sort, you can pass in a "key" argument that is used to map the list items before they are compared:
lo = min(L, key=int)
hi = max(L, key=int)
http://effbot.org/zone/python-list.htm
Looks like you could use the max function if you map it correctly for strings and use that as the comparison. I would recommend just finding the max once though of course, not for each element in the list.
len(each) == max(len(x) for x in myList) or just each == max(myList, key=len)
def LongestEntry(lstName):
totalEntries = len(lstName)
currentEntry = 0
longestLength = 0
while currentEntry < totalEntries:
thisEntry = len(str(lstName[currentEntry]))
if int(thisEntry) > int(longestLength):
longestLength = thisEntry
longestEntry = currentEntry
currentEntry += 1
return longestLength