Merge items in list based on condition - python

I have a list which looks like:
a = ["/n abc", "def", "ghi", "/n jkl", "mno", "/n pqr", "/n stu"]
I want it to look like this:
a = ["abcdefghi", "jklmno" "pqr" "stu"]
Essentially, what I want the code to do is merge items in the list with the item sequentially below until it encounters an element with the substring "/n". It should do this for the entire list and then remove all instances of the substring "/n "

result = [i.strip() for i in ''.join(a).split('/n') if i]
However you should post your attempt first.

Here is my attempt:
res = []
s = ""
for i in l:
if i.startswith("/n"):
if s:
res.append(s)
s = i[3:]
else:
s+=i
if s:
res.append(s)
print(res)

One basic way (without using special methods):
result = []
i = 0
index = 0
while i < len(a):
if a[i][:2] == '\n':
index += 1
result[index] += a[i]
Please correct me if I did something wrong (it's been a long time since I used Python).

Related

Write a function to find the longest common prefix string amongst an array of strings. Index out of range

I am doing a problem where i need to Write a function to find the longest common prefix string amongst an array of strings.
For example :
Input: strs = ["flower","flow","flight"]
Output: "fl"
What I am trying to do, is check each letter indiviudally of each word to see if they are equal. and when they are not then I know that at that moment we have the longest common prefix.After brainstorming for a while, this was the best i could to and went with this idea. However, once I finished my code, it seems to work for some arrays, but most of the time I have an index out of range error. I went to python visualizer to see where I go wrong but everytime I try to change something I get an index error but for a different reason. so after hours of debugging, i gave up and i am now asking for your help to solve this index problem.
for example an index error occurs when i have this array : [ "ab" , "a" ] and more. Im pretty sure my idea is code and my code almost works, so im just asking how to change it, not an entire new code. Thank you
This is my code :
strs = ["ab","a"]
def longestCommonPrefix(strs):
for word in strs:
if word == "":
return ""
if len(strs) == 1:
return strs[0]
common_prefix = ""
j = 0
Common = True
while Common:
for i in range(len(strs) - 1):
if strs[i][j] != strs[i + 1][j]:
Common = False
break
else:
common_prefix += strs[0][j]
j += 1
return common_prefix
print(longestCommonPrefix(strs))
strings = ["a", "ab"]
def find_longest_prefix(data):
shortest_word = min(data, key=len)
for prefix_slice_end in range(len(shortest_word), 0, -1):
if all(i.startswith(shortest_word[0:prefix_slice_end]) for i in data):
return shortest_word[0:prefix_slice_end]
return ''
print(find_longest_prefix(strings))
# >> a
The error is because all strings in the lst do not have the same length, so if you loop over one string length, there might be a chance that some strings have lengths smaller than this. So while using the if condition, try and except block the check for the IndexError.
Try this
strs = ["ab", "a"]
def longestCommonPrefix(strs):
for word in strs:
if word == "":
return ""
if len(strs) == 1:
return strs[0]
common_prefix = ""
j = 0
Common = True
while Common:
for i in range(len(strs) - 1):
try:
if strs[i][j] != strs[i + 1][j]:
Common = False
break
except IndexError:
Common = False
break
else:
common_prefix += strs[0][j]
j += 1
return common_prefix
print(longestCommonPrefix(strs))
If you want some other way then use this one.
def longestCommonPrefix(lst):
for a in range(1, len(lst[0])):
try:
if not all(letter.startswith(lst[0][:a]) for letter in lst[1:]):
return lst[0][:a-1]
except IndexError:
return lst[0][:a-1]
return ""
lst = ["flower", "flow", "flight"]
print(longestCommonPrefix(lst))
def longestCommonPrefix(strs):
if len(strs) == 0:
return ""
current = strs[0]
for i in range(1,len(strs)):
temp = ""
if len(current) == 0:
break
for j in range(len(strs[i])):
if j<len(current) and current[j] == strs[i][j]:
temp+=current[j]
else:
break
current = temp
return current
input_list = ["school","schedule","scotland"]
print(longestCommonPrefix(input_list))

Python Inserting a string

I need to insert a string (character by character) into another string at every 3rd position
For example:- string_1:-wwwaabkccgkll
String_2:- toadhp
Now I need to insert string2 char by char into string1 at every third position
So the output must be wwtaaobkaccdgkhllp
Need in Python.. even Java is ok
So i tried this
Test_str="hiimdumbiknow"
challenge="toadh"
new_st=challenge [k]
Last=list(test_str)
K=0
For i in range(Len(test_str)):
if(i%3==0):
last.insert(i,new_st)
K+=1
and the output i get
thitimtdutmbtiknow
You can split test_str into sub-strings to length 2, and then iterate merging them with challenge:
def concat3(test_str, challenge):
chunks = [test_str[i:i+2] for i in range(0,len(test_str),2)]
result = []
i = j = 0
while i<len(chunks) or j<len(challenge):
if i<len(chunks):
result.append(chunks[i])
i += 1
if j<len(challenge):
result.append(challenge[j])
j += 1
return ''.join(result)
test_str = "hiimdumbiknow"
challenge = "toadh"
print(concat3(test_str, challenge))
# hitimoduambdikhnow
This method works even if the lengths of test_str and challenge are mismatching. (The remaining characters in the longest string will be appended at the end.)
You can split Test_str in to groups of two letters and then re-join with each letter from challenge in between as follows;
import itertools
print(''.join(f'{two}{letter}' for two, letter in itertools.zip_longest([Test_str[i:i+2] for i in range(0,len(Test_str),2)], challenge, fillvalue='')))
Output:
hitimoduambdikhnow
*edited to split in to groups of two rather than three as originally posted
you can try this, make an iter above the second string and iterate over the first one and select which character should be part of the final string according the position
def add3(s1, s2):
def n():
try:
k = iter(s2)
for i,j in enumerate(s1):
yield (j if (i==0 or (i+1)%3) else next(k))
except:
try:
yield s1[i+1:]
except:
pass
return ''.join(n())
def insertstring(test_str,challenge):
result = ''
x = [x for x in test_str]
y = [y for y in challenge]
j = 0
for i in range(len(x)):
if i % 2 != 0 or i == 0:
result += x[i]
else:
if j < 5:
result += y[j]
result += x[i]
j += 1
get_last_element = x[-1]
return result + get_last_element
print(insertstring(test_str,challenge))
#output: hitimoduambdikhnow

Divide string into pairs [duplicate]

This question already has answers here:
Split string every nth character?
(19 answers)
Splitting a string into 2-letter segments [duplicate]
(6 answers)
Closed 2 years ago.
I want to divide text into pairs.
Input: text = "abcde"
Goal Output: result = ["ab", "cd", "e_"]
Current Output: result = ['ab', 'abcd']
My current code looks like this. But I do not know how I do that now. Anyone has a tip for me?
def split_pairs(text):
result = []
if text is None or not text:
return []
pair = ""
for i in range(len(text)):
if i % 2 == 0:
pair += text[i]
pair += text[i+1]
else:
result.append(pair)
return result
You could use a list comprehension to zip together the even values with the corresponding odd values. And using itertools.zip_longest you can use the fillvalue argument to provide a "fill in" if there is a length mismatch.
>>> from itertools import zip_longest
>>> s = 'abcde'
>>> pairs = [i+j for i,j in zip_longest(s[::2], s[1::2], fillvalue='_')]
>>> pairs
['ab', 'cd', 'e_']
You should reset your "pair" variable once appended to "result"
def split_pairs(text):
result = []
if text is None or not text:
return []
pair = ""
for i in range(len(text)):
if i % 2 == 0:
pair += text[i]
pair += text[i+1]
else:
result.append(pair)
pair = ""
return result
You could also use a list comprehension over a range with 3rd step parameter and add ljust to add _. This will also work nicely for more than just pairs:
>>> s = "abcde"
>>> k = 2
>>> [s[i:i+k].ljust(k, "_") for i in range(0, len(s), k)]
['ab', 'cd', 'e_']
I am not if your code needed to be in the format you originally wrote it in, but I wrote the below code that gets the job done.
def split_pairs(text):
if len(text) % 2 == 0:
result = [text[i:i+2] for i in range(0, len(text), 2)]
else:
result = [text[i:i+2] for i in range(0, len(text), 2)]
result[-1]+="_"
return result
The issue here is that the "pair" variable is never reinitialized to "".
Make sure you make it an empty string in your else block.
def split_pairs(text):
result = []
if text is None or not text:
return []
pair = ""
for i in range(len(text)):
if i % 2 == 0:
pair += text[i]
pair += text[i+1]
else:
result.append(pair)
pair = "" # Make sure you reset it
return result
If you want to have a "_" at the end (in case of an odd number of character), you could do like the following:
def split_pairs(text):
result = []
if text is None or not text:
return []
pair = "__" # Setting pair to "__" by default
for i in range(len(text)):
if i % 2 == 0:
pair[0] = text[i]
if i < len(text): # Avoiding overflow
pair[1] = text[i+1]
else:
result.append(pair)
pair = "__" # Make sure you reset it
if pair != "__": # Last bit
result.append(pair)
return result

Check the most frequent letter(s) in a word. Python

My task is:
To write a function that gets a string as an argument and returns the letter(s) with the maximum appearance in it.
Example 1:
s = 'Astana'
Output:
a
Example 2:
s = 'Kaskelen'
Output:
ke
So far, I've got this code(click to run):
a = input()
def most_used(w):
a = list(w)
indexes = []
g_count_max = a.count(a[0])
for letter in a:
count = 0
i = int()
for index in range(len(a)):
if letter == a[index] or letter == a[index].upper():
count += 1
i = index
if g_count_max <= count: //here is the problem.
g_count_max = count
if i not in indexes:
indexes.append(i)
letters = str()
for i in indexes:
letters = letters + a[i].lower()
return letters
print(most_used(a))
The problem is that it automatically adds first letter to the array because the sum of appearance of the first element is actually equal to the starter point of appearance(which is basically the first element).
Example 1:
s = 'hheee'
Output:
he
Example 2:
s = 'malaysia'
Output:
ma
I think what you're trying to can be much simplified by using the standard library's Counter object
from collections import Counter
def most_used(word):
# this has the form [(letter, count), ...] ordered from most to least common
most_common = Counter(word.lower()).most_common()
result = []
for letter, count in most_common:
if count == most_common[0][1]:
result.append(letter) # if equal largest -- add to result
else:
break # otherwise don't bother looping over the whole thing
return result # or ''.join(result) to return a string
You can use a dictionary comprehension with a list comprehension and max():
s = 'Kaskelen'
s_lower = s.lower() #convert string to lowercase
counts = {i: s_lower.count(i) for i in s_lower}
max_counts = max(counts.values()) #maximum count
most_common = ''.join(k for k,v in counts.items() if v == max_counts)
Yields:
'ke'
try this code using list comprehensions:
word = input('word=').lower()
letters = set(list(word))
max_w = max([word.count(item) for item in letters])
out = ''.join([item for item in letters if word.count(item)==max_w])
print(out)
Also you can import Counter lib:
from collections import Counter
a = "dagsdvwdsbd"
print(Counter(a).most_common(3)[0][0])
Then it returns:
d

Slice a list to max string size

I have a max length of a list item that I need to enforce. How would I accomplish the following:
MAX_LENGTH = 13
>>> str(["hello","david"])[:MAX_LENGTH]
"['hello', 'da"
==> ["hello", "da"]
I was thinking using ast.literal_eval, but was wondering what might be recommended here.
I would caution against this. There has to be safer things to do than this. At the very least you should never be splitting elements in half. For instance:
import sys
overrun = []
data = ["Hello,"] + ( ["buffer"] * 80 )
maxsize = 800
# sys.getsizeof(data) is now 840 in my implementation.
while True:
while sys.getsizeof(data) > maxsize:
overrun.append(data.pop())
do_something_with(data)
if overrun:
data, overrun = overrun, []
else:
break
Here is a simplified version of #AdamSmith's answer which I ended up using:
import sys
from copy import copy
def limit_list_size(ls, maxsize=800):
data = copy(ls)
while (sys.getsizeof(str(data)) > maxsize):
if not data: break
data.pop()
return data
Note that this will not split mid-word. And because this is returning a copy of the data, the user can see which items were excluded in the output. For example:
old_ls = [...]
new_ls = limit_list_size(old_ls)
overflow_ls = list(set(old_ls) - set(new_ls))
If you want MAX_LENGTH of your strings concatenated, you could do it with a loop pretty simply, using something like this:
def truncateStringList(myArray)
currentLength = 0
result = []
for string in myArray:
if (currentLength + len(string)) > MAX_LENGTH:
result.append(string[:len(string) + currentLength - MAX_LENGTH])
return result
else:
result.append(string)
return result
If you want it of the string representation, you are effectively adding 2 chars at the beginning of each element, [' or ', and two at the end, ', or '], so add 2 to current length before and after each element in the loop:
for string in myArray:
currentLength += 2
if (currentLength + len(string)) > MAX_LENGTH:
result.append(string[:len(string) + currentLength - MAX_LENGTH])
return result
else:
result.append(string)
currentLength += 2
return result
with loops:
max = 11
mylist = ['awdawdwad', 'uppps']
newlist = ','.join(mylist)
print mylist
c= [x for x in newlist if not x==',']
if len(c)>max:
newlist= list(newlist)
newlist.reverse()
for x in range(len(c)-max):
if newlist[0]==',':
del newlist[0]
del newlist[0] # delete two times
else:
del newlist[0]
while newlist[0]==',':
del newlist[0]
newlist.reverse()
cappedlist = ''.join(newlist).split(',')
print cappedlist

Categories

Resources