create list from list where values only increase by 1 - python-3.x

I have the code below that gets the maximum value from a list. It then compares it to the maximum value of the remaining values in the list, and if it is more than 1 higher than the next greatest value, it replaces the original list maximum with 1 higher than the next greatest value. I would like the code to search the entire list and make sure that any value in the list is at most 1 larger than any other value in the list. I know this ins’t the best worded explanation, I hope the example lists below make what I’m trying to accomplish clearer.
for example I don’t want to get a final list like:
[0,2,0,3]
I would want the final list to be
[0,1,0,2]
input:
empt=[0,2,0,0]
Code:
nwEmpt=[i for i in empt if i !=max(empt)]
nwEmpt2=[]
for i in range(0,len(empt)):
if (empt[i]==max(empt))&(max(empt)>(max(nwEmpt)+1)):
nwEmpt2.append((max(nwEmpt)+1))
elif (empt[i]==max(empt))&(max(empt)==(max(nwEmpt)+1)):
nwEmpt2.append(max(empt))
else:
nwEmpt2.append(empt[i])
output:
nwEmpt2
[0,1,0,0]

min_value = min(empt)
empt_set = set(empt)
for i in empt:
nwEmpt.append(min_value + len(list(filter(lambda x: x < i, empt_set))))
This gives e.g. for input empt = [8, 10, 6, 4, 4] output nwEmpt = [6, 7, 5, 4, 4].
It works by mapping each element to (the minimum value) + (the number of distinct values smaller than element).

Related

Getting rid of duplicates from a pair of corresponding lists

This is a program that I recently made. The goal of this code is to a pair of corresponding lists. So randomStringpt1[0] corresponds to randomStringpt2[0]. I want to compare randomStringpt1[0] and randomString2[0] to the rest of the pairs that the user gave in the randomStrings. But after using this code, it looks like I have duplicated each pair many times, which is the opposite of what I was looking for. I was thinking of using a dictionary, but then realized that a dictionary key could only have one value, which wouldn't help my case if the user used a number twice. Does anyone know how I can reduce the duplicates?
(The tests I have been running have been with the numbers randomStringpt1 = [1,3,1,1,3] and randomStringpy2 = [2,4,2,3,4]
)
randomStringpt1 = [1, 2, 3, 4, 5] #Pair of strings that correspond to each other("1,2,3,4,5" doesn't actually matter)
randomStringpt2 = [1, 2, 3, 4, 5]
for i in range(len(randomStringpt1)):
randomStringpt1[i] = input("Values for the first string: ")
randomStringpt2[i] = input("Corresponding value for the second string: ")
print(randomStringpt1) #numbers that the user chose for the first number of the pair
print(randomStringpt2) #numbers that the user chose for the second number of the pair
newStart = []
newEnd = []
for num1 in range(len(randomStringpt1)):
for num2 in range(len(randomStringpt1)):
if (int(randomStringpt1[num1]) != int(randomStringpt1[num2]) and int(randomStringpt2[num1]) != int(randomStringpt2[num2])):
newStart.append(randomStringpt1[num1]) # Adding the pairs that aren't equal to each other to a new list
newEnd.append(randomStringpt2[num1])
newStart.append(randomStringpt1[num2])
newEnd.append(randomStringpt2[num2])
# else:
# print("The set of numbers from the randomStrings of num1 are not equal to the ones in num2")
print(newStart)
print(newEnd)
First let's analyze the 2 bugs in your code,
the if condition inside the loop is true every time a pair compares to a different one. this means for your example it should output
[1, 1, 3, 3, 3, 1, 1, 1, 1, 3, 3, 3]
[2, 2, 4, 4, 4, 2, 2, 3, 3, 4, 4, 4]
since you compare every pair to any other pair that exists. But your output is different because you append both pairs every time and getting a very big result, so you shouldn't append the num2 pairs.
Now, from what you described that you want, you should loop every pair and check if it already exists in the output list. So the for loop part can change like this
filtered = []
for pair in zip(randomStringpt1,randomStringpt2):
if pair not in filtered:
filtered.append(pair) # Adding the pairs that aren't equal to each other to a new list
the zip function takes the 2 lists and for every loop it returns 2 values one from each list the first value pair, then the second values and goes on. the filtered list will be in the following format [(1, 2), (3, 4), (1, 3)]
Alternative it can be as a one liner like this:
filtered = list(dict.fromkeys(zip(randomStringpt1, randomStringpt2)))
using the dictionary to identify unique elements and then turn it back into a list
after all that you can get the original format of the lists you had in your code by splitting them like this
newStart = [pair[0] for pair in filtered]
newEnd = [pair[1] for pair in filtered]
Finally i should tell you to read a little more on python and it's for loops, since the range(len(yourlist)) is not the python intended way to loop over lists, as python for loops are equivalent to for each loops on other languages and iterate over the list for you instead on relying in a value to get list elements like yourlist[value].

Algorithm for calculating the duplicates in a list

The code below prints out the numbers which are duplicated in A.
From my understanding, the for loop goes through each element in the list and turns it into a negative number, though i can not figure out why it does not turn the numbers it prints (which are at at position 0,4,5) negative.
A = [1,2,3,1,3,6,6]
def printRepeating(arr, size):
print("The repeating elements are: ")
for i,x in enumerate(arr):
if arr[abs(arr[i])] >= 0:
arr[abs(arr[i])] = -arr[abs(arr[i])]
print(arr)
else:
print (abs(arr[i]), end = " ")
printRepeating(A,len(A))
The algorithm assumes:
all the elements of the array start as positive numbers, and
all the elements of the array are less than the length of the array.
In your example, since the length of the array is 7, all the elements in the array must be between 1 and 6.
What the algorithm does is change array[k] to negative to indicate that k has been seen. For example, since 1 is the first number seen, array[1] is changed to a negative number. The next time 1 is seen, array[1] is already negative, so 1 must be a duplicate.
If you just want to print the repeated values in the list then why not try this:
A = [1, 2, 3, 1, 3, 6, 6]
def get_repeated_elements(lst):
return list(set((i for i in lst if lst.count(i) > 1)))
print(get_repeated_elements(A))
This function converts the passed array into a generator of duplicated values
and then converts this into a set to filter out duplicates in the generator and then converts this into a list for returning to the caller. This is a far shorter function than the one given.
The algorithm assumes that all entries are strictly positive and smaller than the length of the list. Then, what it does is essentially using the sign of the i-th element to store if it already saw number i. In your example:
A=[1,2,3,1,3,6,6] Take 1
A[1] is positive, i.e. we have not seen it. Make it negative to mark it
A=[1,-2,3,1,3,6,6] Take -2 (stands for 2)
A[2] is positive, i.e. we have not seen it. Make it negative to mark it
A=[1,-2,-3,1,3,6,6] Take -3
A[3] is positive, i.e. we have not seen it. Make it negative to mark it
A=[1,-2,-3,-1,3,6,6] Take -1
A[1] is negative, i.e. we have already seen it. Report it.
A=[1,-2,-3,-1,3,6,6] Take 3
A[3] is negative, i.e. we have already seen it. Report it.
...
The below code can be used to find repeated elements in the list and also unique elements in the list.
from collections import Counter
A = [1,2,3,1,3,6,6]
B = Counter(A)
The below line prints repeated elements.
[k for k, v in B.items() if v > 1]
Output : [1, 3, 6]
The below line prints unique elements.
[k for k, v in B.items() if v == 1]
Output : [2]

In the case of a tie, how do I return the largest and most frequent number in python?

I have a list of numbers. I created this frequency dictionary d:
from collections import Counter
mylist = [10, 8, 12, 7, 8, 8, 6, 4, 10, 12, 10, 12]
d = Counter(mylist)
print(d)
The output is like this:
Counter({10: 3, 8: 3, 12: 3, 7: 1, 6: 1, 4: 1})
I know I can use max(d, key=d.get) to get value if there is no tie in frequency. If multiple items are maximal, the function usually returns the first one encountered. How can I return the largest number, in this case, 12, instead of 10? Thank you for your help!
Define a lambda function that returns a tuple. Tuples are sorted by their first value, and then tie-broken by subsequent values. Like this:
max(d, key=lambda x:(d.get(x), x))
So for the two example values, the lambda will return (3, 10) and (3, 12). And of course, the second will be considered the max.
Further explanation:
When the max function is given a collection to find the max of, and a key, it will go over the values in the collection, passing each value into the key function. Whatever element from the collection results in the maximal output from the key function is considered the maximal value.
In this case, we're giving it a lambda function. Lambdas are just functions. Literally no difference in their usage, just a different syntax for defining them. The above example could have been written as:
def maxKey(x):return (d.get(x), x)
max(d, key=maxKey)
and it would behave the same way.
Using that function, we can see the return values that it would give for your sample data.
maxKey(10) #(3, 10)
maxKey(12) #(3, 12)
The main difference between the anonymous lambda above and using d.get is that the lambda returns a tuple with two values in it.
When max encounters a tie, it returns the first one it saw. But because we're now returning tuples, and because we know that the second value in each tuple is unique (because it comes from a dictionary), we can be sure that there won't be any duplicates. When max encounters a tuple it first compares the first value in the tuple against whatever it has already found to be the maximal value. If there's a tie there, it compares the next value. If there's a tie there, the next value, etc. So when max compares (3, 10) with (3, 12) it will see that (3, 12) is the maximal value. Since that is the value that resulted from 12 going into the key function, max will see 12 as the maximal value.
You can get the max count (using d.most_common), and then get the max of all keys that have the max count:
max_cnt = d.most_common(1)[0][1]
grt_max = max(n for n, cnt in d.items() if cnt == max_cnt)
print(grt_max)
Output:
12

Remove number from list in which difference between two number are less then specific number

a = [2, 5, 6, 12, 21, 25, 32, 41]
This is my list and I want to remove all the numbers which are not in difference of 7.
Before diving into the answers, let's go over what we're dealing with.
You got a list 'A', which you need to loop through to get a list of numbers that are greater than the previous value + 7
If you boil down the question, you get left with two main goals
We need a loop
and we have a list with the final answer
There are two generic ways of approaching this question. In a loop, we populate a new list. The second way is to manipulate the original list.
Although the First approach requires additional memory, I'll be using the First approach for simplicity.
a = [2, 5, 6, 12, 21, 25, 32, 41] # your original list
b = [] # Empty list that will contain final product
for i in range(len(a)):
if len(b) == 0: # if the list is empty, we add first item from 'a' (In our example, it'll be 2)
b.append(a[i])
else:
if a[i] > b[len(b)-1]+7 or a[i] < b[len(b)-1]-7: # for every value of a, we compare the last digit from list b
b.append(a[i])
As far as I have understood your question, in your output list, only those elements should be there whose sum is 7. So that can be achieved by
i=1;
while i<len(a):
if(a[i]-a[i-1] < 7):
a.remove(a[i])
else:
i+=1
print(a)

How to get list of indices for elements whose value is the maximum in that list

Suppose I have a list l=[3,4,4,2,1,4,6]
I would like to obtain a subset of this list containing the indices of elements whose value is max(l).
In this case, list of indices will be [1,2,5].
I am using this approach to solve a problem where, a list of numbers are provided, for example
l=[1,2,3,4,3,2,2,3,4,5,6,7,5,4,3,2,2,3,4,3,4,5,6,7]
I need to identify the max occurence of an element, however in case more than 1 element appears the same number of times,
I need to choose the element which is greater in magnitude,
suppose I apply a counter on l and get {1:5,2:5,3:4...}, I have to choose '2' instead of '1'.
Please suggest how to solve this
Edit-
The problem begins like this,
1) a list is provided as an input
l=[1 4 4 4 5 3]
2)I run a Counter on this to obtain the counts of each unique element
3)I need to obtain the key whose value is maximum
4)Suppose the Counter object contains multiple entries whose value is maximum,
as in Counter{1:4,2:4,3:4,5:1}
I have to choose 3 as the key whose value is 4.
5)So far, I have been able to get the Counter object, I have seperated key/value lists using k=counter.keys();v=counter.values()
6)I want to get the indices whose values are max in v
If I run v.index(max(v)), I get the first index whose value matches max value, but I want to obtain the list of indices whose value is max, so that I can obtain corresponding list of keys and obtain max key in that list.
With long lists, using NumPy or any other linear algebra would be helpful, otherwise you can simply use either
l.index(max(l))
or
max(range(len(l)),key=l)
These however return only one of the many argmax's.
So for your problem, you can choose to reverse the array, since you want the maximum that appears later as :
len(l)-l[::-1].index(max(l))-1
If I understood correctly, the following should do what you want.
from collections import Counter
def get_largest_most_freq(lst):
c = Counter(lst)
# get the largest frequency
freq = max(c.values())
# get list of all the values that occur _max times
items = [k for k, v in c.items() if v == freq]
# return largest most frequent item
return max(items)
def get_indexes_of_most_freq(lst):
_max = get_largest_most_freq(lst)
# get list of all indexes that have a value matching _max
return [i for i, v in enumerate(lst) if v == _max]
>>> lst = [3,4,4,2,1,4,6]
>>> get_largest_most_freq(lst)
4
>>> get_indexes_of_most_freq(lst)
[1, 2, 5]
>>> lst = [1,2,3,4,3,2,2,3,4,5,6,7,5,4,3,2,2,3,4,3,4,5,6,7]
>>> get_largest_most_freq(lst)
3
>>> get_indexes_of_most_freq(lst)
[2, 4, 7, 14, 17, 19]

Resources