Removing multiple elements from a list - python-3.x

In this program I have entered the elements of a list and have to find the second highest element,to achieve that I have created a separate list with the same values of original list,removed the highest element,sort in descending order and print the first element. However,the highest element is 95 and occurs twice in the list but by using the following code, only one 95 gets removed from the list
marks_list2 = marks_list
high = float(max(marks_list))
for j in marks_list:
if j==high:
marks_list2.remove(j)
marks_list2.sort(reverse=True)
print('The second highest element is:',marks_list2[0])
Can anyone help me rectify the code and also tell me where I went wrong with my logic. Thanks in advance!

The python built in set() method removes all the repetitions.
marks_list = set(marks_list)
marks_list.remove(max(marks_list))
print('The second highest element is: %s' % max(marks_list))

Related

how to separate the list into nested list ,with the average of all elements in the list?

i need to separate the list into nested list with its average value.
a =[ 0.6140781, 0.61407846, 0.6930427, 0.6930429, 0.7213439, 0.72134393, 0.7333274, 0.73332757]
the average of the list is 0.05515
if the difference between two elements is not more than 0.5515 ,i need to join the elements in the list and if the next element in list exceeds 0.05515 then form the another list in python
desired output:
output : [[0.6140781, 0.61407846],[0.6930427, 0.69460429],[0.7213439, 0.72334393], [0.7333274, 0.73532757]]
Any suggestions would be helpful!
Since the list is sorted, you can iterate through, if the current element is greater than target value, add a new list to the output, and add the current element to the most recently added list.
Your output doesn't make sense with the average number you provided because 0.7213439 - 0.69460429 is not greater than 0.05515, neither is 0.7333274 - 0.72334393 so I used 0.01 instead.
a = [0.6140781, 0.61407846, 0.6930427, 0.6930429, 0.7213439, 0.72134393, 0.7333274, 0.73332757]
output = [a[:1]]
for i in range(1, len(a)):
if a[i] - a[i-1] > 0.01:
output.append([])
output[-1].append(a[i])
print(output)

Defining a function to find the unique palindromes in a given string

I'm kinda new to python.I'm trying to define a function when asked would give an output of only unique words which are palindromes in a string.
I used casefold() to make it case-insensitive and set() to print only uniques.
Here's my code:
def uniquePalindromes(string):
x=string.split()
for i in x:
k=[]
rev= ''.join(reversed(i))
if i.casefold() == rev.casefold():
k.append(i.casefold())
print(set(k))
else:
return
I've tried to run this line
print( uniquePalindromes('Hanah asked Sarah but Sarah refused') )
The expected output should be ['hanah','sarah'] but its returning only {'hanah'} as the output. Please help.
Your logic is sound, and your function is mostly doing what you want it to. Part of the issue is how you're returning things - all you're doing is printing the set of each individual word. For example, when I take your existing code and do this:
>>> print(uniquePalindromes('Hannah Hannah Alomomola Girafarig Yes Nah, Chansey Goldeen Need log'))
{'hannah'}
{'alomomola'}
{'girafarig'}
None
hannah, alomomola, and girafarig are the palindromes I would expect to see, but they're not given in the format I expect. For one, they're being printed, instead of returned, and for two, that's happening one-by-one.
And the function is returning None, and you're trying to print that. This is not what we want.
Here's a fixed version of your function:
def uniquePalindromes(string):
x=string.split()
k = [] # note how we put it *outside* the loop, so it persists across each iteration without being reset
for i in x:
rev= ''.join(reversed(i))
if i.casefold() == rev.casefold():
k.append(i.casefold())
# the print statement isn't what we want
# no need for an else statement - the loop will continue anyway
# now, once all elements have been visited, return the set of unique elements from k
return set(k)
now it returns roughly what you'd expect - a single set with multiple words, instead of printing multiple sets with one word each. Then, we can print that set.
>>> print(uniquePalindromes("Hannah asked Sarah but Sarah refused"))
{'hannah'}
>>> print(uniquePalindromes("Hannah and her friend Anna caught a Girafarig and named it hannaH"))
{'anna', 'hannah', 'girafarig', 'a'}
they are not gonna like me on here if I give you some tips. But try to divide the amount of characters (that aren't whitespace) into 2. If the amount on each side is not equivalent then you must be dealing with an odd amount of letters. That means that you should be able to traverse the palindrome going downwards from the middle and upwards from the middle, comparing those letters together and using the middle point as a "jump off" point. Hope this helps

Improve execution time of code so that it does not time out

I have a piece of code that works is some of case ,but some case this take more time and give time out issue.can someone please help to improve this?
[Edit]:let me explain the how it is working
function accepts a list as input
function returns a list as output as follows:
1.The smallest number of list should be in middle
2.Next smallest number should be append at the end of list
3.Next smallest number should be appended at the start of list
4.Next smallest number should be append at the end of list
5.Next smallest number should be appended at the start of list
4.it continues ......unless we scan all input list
def pendulum(values):
result=[]
while(len(values)):
min_num=min(values)
result.insert(0,min_num)
values.remove(min_num)
if len(values)>0:
min_num=min(values)
result.insert(len(result),min_num)
values.remove(min_num)
return result
The biggest problem is that your code searches for the minimum once per element. Pre-sorting the list will make it much faster. You are also inserting at the front of the list, which forces every element of the list to be moved, for every other element. To combat this, I just use append, and then reverse the front half of the list.
def pendulum(values):
front = []
back = []
next_goes_to_front = True
for value in sorted(values):
if next_goes_to_front:
front.append(value)
else:
back.append(value)
next_goes_to_front = not next_goes_to_front
return list(reversed(front)) + back

Python: Using a For Loop and random function in statistical probabiltiy model

I have been set a task, to using an original Dataset of 25 A's and C's (50 data points in total), to randomly select 1 of the 50 data points then add this to a new nested list and to repeat this 50 times (length of dataset). This random selection then needs to be done again with the new dataset, for 25 times.
import random
SetSize = 50
StatData = [[] for b in range(1,50)]
for i in range(0, int(SetSize/2)):
StatData[0].append('A')
for i in range(int(SetSize/2)):
StatData[0].append('C')
for a in range(1,25):
for b in range(0, int(SetSize)):
StatData(a+1).append(random.choice(StatData[a]))
This is my current piece of code, so i have created the empty nested list, created the initial dataset (StatData0) however the next section is not working it is returning
"TypeError: 'list' object is not callable"
Any help would be much appreciated!
The error says it all. You cannot call a list.
Typo
On the last line of the code you provided, change
StatData(a+1).appen...
to
StatData[a+1].appen...
and I guess it should fix the error.
Index problem (edit)
You are populating the list of index 0 with As and Bs (StatData[0]) but in your last loop a goes from 1 to 50. So your first iteration will choose a random character in StatData[1] (which is empty) thus throwing another error.
Starting your loop from the index 0 should make this go away !

Python: iterate through list and check for matching sub-string in specific parts of string

for all the strings in a list of strings, if either of the first two characters of the string match (in any order) then check if either of last two strings match in specific order. If so, I will ad an edge between two vertex in graph G.
Example:
d = ['BEBC', 'ABRC']
since the 'B' in the first two characters and the 'C' in the second two characters match, I will add an edge. I'm fairly new to Python and what I have come up with through previous searches seems overly verbose:
for i in range(0,len(d)-1):
for j in range(0,len(d)-1):
if (d[i][0] in d[j+1][:2] or d[i][1] in d[j+1][:2]) and \
(d[i][2] in d[j+1][2] or d[i][3] in d[j+1][3]):
G.add_edge(d[i],d[j+1])
The next step on this is to come up with a faster way to iterate through since there will probably only be 1 to 3 edges connecting each node, so 90% of the iteration test will come back false. Suggestions would be welcome!
Since you know that the last character of each list item needs to absolutely match in the same place it's less expensive to check for that first. The code is otherwise doing unnecessary work even though it really doesn't need to. Using timeit you can determine the difference in calculation time by making a few changes, such as checking for the last characters first:
import timeit
d = ['BEBC', 'ABRC']
def test1():
if (d[0][len(d[0])-1] is d[1][len(d[1])-1]):
for i in range(0,2):
if(d[0][i] in d[1][:2]):
return(d[0],d[1])
print(test1())
print(timeit.timeit(stmt=test1, number=1000000))
Result:
('BEBC', 'ABRC')
2.3587113980001959
Original Code:
d = ['BEBC', 'ABRC']
def test2():
for i in range(0,len(d)-1):
for j in range(0,len(d)-1):
if (d[i][0] in d[j+1][:2] or d[i][1] in d[j+1][:2]) and \
(d[i][2] in d[j+1][2] or d[i][3] in d[j+1][3]):
return(d[i],d[j+1])
print(test2())
print(timeit.timeit(stmt=test2, number=1000000))
Result:
('BEBC', 'ABRC')
3.1525327970002763
Now let's take the last list value and change it so that the last character C does not match:
d = ['BEBC', 'ABRX']
New Code:
None
0.766526217000318
Original:
None
2.963771982000253
This is where it's obviously going to pay off in regard to the order of iterating items — especially considering if 90% of the iteration checks could come back false.

Resources