Sorting Elements of an Array by Frequency - python

I want to solve this question using dict in python.However i am not able to create code out of the logic.
question says Given an array A[] of integers, sort the array according to frequency of elements. That is elements that have higher frequency come first. If frequencies of two elements are same, then smaller number comes first.
Input:
2
5
5 5 4 6 4
5
9 9 9 2 5
Output:
4 4 5 5 6
9 9 9 2 5
t=int(input())
for i in range(t):
n=int(input())
arr=list(map(int,input().split()))
d={}
for i in arr:
d[i]=d.get(0,i)+1
a=max(d[i])
print(i*d[i])
a=a+1
Little bit of code that I tried is as above

import collections
sample = [1, 9, 1, 1, 10, 10, 7, 1, 2, 2, 2, 0, 2, 3, 3, 4, 0, 5]
counter = collections.Counter(sample)
def helper_function(item):
return counter[item], item # returns a tuple
sorted_list = sorted(sample, key=helper_function)
# or if you prefer using lambda
sorted_list = sorted(sample, key=lambda item: (counter[item], item))
print(sorted_list)
Output:
[4, 5, 7, 9, 0, 0, 3, 3, 10, 10, 1, 1, 1, 1, 2, 2, 2, 2]

Related

I have problem with removing last item from list [duplicate]

This question already has answers here:
How to remove items from a list while iterating?
(25 answers)
Closed 1 year ago.
nums = [0,1,2,2,3,0,4,2]
val = 2
for i in nums:
if i == val:
nums.remove(i)
else:
continue
print(nums)
Result is [0,1,3,0,4,2] instead of [0,1,3,0,4]
Well maybe I am a little bit confused because in the title you ask for removing just the last item but in the question you ask for an expected result. I just took your code and make it work to get the expected output with a list comprehension. It looks like this:
nums_new = [i for i in nums if i != val]
You can ofcourse name nums_new to only nums.
Your mistake becomes clear if you print your data inside the loop:
nums = [0,1,2,2,3,0,4,2]
val = 2
for i in nums:
if i == val:
nums.remove(i)
print(i, nums)
print(nums)
Output:
0 [0, 1, 2, 2, 3, 0, 4, 2]
1 [0, 1, 2, 2, 3, 0, 4, 2]
2 [0, 1, 2, 3, 0, 4, 2]
3 [0, 1, 2, 3, 0, 4, 2]
0 [0, 1, 2, 3, 0, 4, 2]
4 [0, 1, 2, 3, 0, 4, 2]
2 [0, 1, 3, 0, 4, 2]
[0, 1, 3, 0, 4, 2]
Note:
i goes through 0, 1, 2, 3, ..., i.e., not two 2s in a row. That's because you remove the first 2, but "the loop" doesn't care, it still goes to the next position in the list, which then holds the value 3.
You do find the 2 at the end, but since remove removes the first occurrence, it removes the earlier 2.
You have a few options:
Filter
your_list = [1, 2, 3, 4, 2, 3, 4, 2]
filtered_values = filter(lambda value: value != 2, your_list)
The first argument is the filtering function, the second is your values - whatever evaluates to False is removed from the list.
List comprehension
your_list = [1, 2, 3, 4, 2, 3, 4, 2]
filtered_values = [value for value in your_list if value != 2]
There are many other ways of doing it, although those are the most common ways of doing it.
You can also do this with the NumPy module:
import numpy as np
# generate 20 random integers between 0 (inclusive) and 5 (exclusive)
myarr = np.random.randint(0, 5, 20)
print(myarr)
[0 2 0 1 2 0 3 0 0 0 3 4 1 3 1 4 1 0 4 4]
val = 2
myarr = np.delete(myarr, np.where(myarr == val))
print(myarr)
[0 0 1 0 3 0 0 0 3 4 1 3 1 4 1 0 4 4]
myarr = np.delete(myarr, np.where(myarr == val))
In that line we do the following: from the array myarr, delete the elements whenever that element equals val.
The same can be achieved with your initial list, by first converting it to a numpy array:
nums = np.array(nums)

Return a list of Element by discarding the Sequential Occurrence of Elements

i/p 1:
test_list = [1, 1, 3, 4, 4, 4, 5,6, 6, 7, 8, 8, 6]
o/p
[3, 5, 7, 6]
Exp: Since (1 1), (4 4 4) (6 6) (8 8) are in consecutive occurrence so resultant list has no addition of 6 but for last occurrence where 8, 6 are not in multiple consecutive occurrence so 6 is valid
in last iteration
i/p 2:
test_list = [1, 1, 3, 4, 4, 4, 5,4,6, 6, 7, 8, 8, 6]
o/p
[3, 5,4, 7, 6]
** like wise for 2nd input 4,4,4 is not valid but 5,4 is valid
Any suggestion for the expected o/p?
(I am looking for bit elaborated algorithm)
You can use itertools.groupby to group adjacent identical values, then only keep values that have group length of 1.
>>> from itertools import groupby
>>> test_list = [1, 1, 3, 4, 4, 4, 5,6, 6, 7, 8, 8, 6]
>>> [k for k, g in groupby(test_list) if len(list(g)) == 1]
[3, 5, 7, 6]
>>> test_list = [1, 1, 3, 4, 4, 4, 5,4,6, 6, 7, 8, 8, 6]
>>> [k for k, g in groupby(test_list) if len(list(g)) == 1]
[3, 5, 4, 7, 6]
First of all, you need to know that increasing i in your for loop does not change the value of i.
You can check it by runin this code:
for i in range(5):
print(i)
i = 2
This code will print 0 1 2 3 4 not 0 2 2 2 2 as you might think.
Going back to your question. I would use groupby from itertools, but since you specified you don't want to use it, I would do something like this:
if test_list[0] != test_list[1]: # <-- check if first element should belong to result
res_list.append(test_list[0])
for i in range(len(test_list[1:-1])): # Here we use input list, but without first and last element.
if test_list[i+1] == test_list[i+2] or test_list[i+1] == test_list[i]:
continue
else:
res_list.append(test_list[i+1])
if test_list[-2] != test_list[-1]: # <-- check if last element should belong to result
res_list.append(test_list[-1])

How to resample an array by duplicating/skipping every N item?

I am confused on how to achieve the following:
Say I have an array of size X (e.g: 3000 items). I want to create a function that will stretch that array to size Y (e.g: 4000) by duplicating every N item.
Along with another function to do the opposite, remove every N items to make the array size 2000 for example.
I guess this is more of a math problem than a programming problem, and as you can tell maths aren't my strong point. Here's what I have so far:
def upsample(originalArray, targetSize):
newArray = []
j = 0
for i in range (0, len(originalArray)):
newArray.append(originalArray[i])
# calculate at what interval items need to be duplicated
# this is what I'm having trouble with
if j == interval:
newArray.append(originalArray[i])
j = 0
j+=1
return newArray
Here is an example of what I'm trying to do:
# stretch array from 10 to 12 items
originalArray = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
upsample(originalArray, 11)
# output: [0, 1, 2, 3, 4, 4, 5, 6, 7, 8, 9, 9]
Any help will be much appreciated
Create a floating point linspace and map it back to integer to use it as indices for your original Array. (Since you wanted [0, 1, 2, 3, 4, 4, 5, 6, 7, 8, 9, 9] instead of [0, 0, 1, 2, 3, 4, 4, 5, 6, 7, 8, 9] you need to do this flipping stuff in the if condition).
The code avoids loops for performance.
import numpy as np
def upsample(originalArray, targetSize):
x = np.linspace(0, originalArray.size, num=targetSize, endpoint=False)
if targetSize > originalArray.size:
x = -np.flip(x, axis=0) + originalArray.size
x[-1] = originalArray.size - 1
x = originalArray[x.astype(int)]
return x
upsample(originalArray, 21) gives [0 0 1 1 2 2 3 3 4 4 5 5 6 6 7 7 8 8 9 9 9]
upsample(originalArray, 23) gives [0 0 1 1 2 2 3 3 3 4 4 5 5 6 6 6 7 7 8 8 9 9 9]
upsample(originalArray, 5) gives [0 2 4 6 8]
etc.
To downsample your array:
N =2 #downsampling by 2
new = originalArray[0:N:]
To upsample (a being originaArray):
new = [item for t in [[a[i]]*2 if i%N==0 else [a[i],] for i in range(0,len(a))] for item in t]
or more explicitly:
res = list()
i=0
while(i<len(originalArray)):
res.append(originalArray[i])
if i%N==0:
continue
i +=1

recursion, Python, countup, countdown

I am supposed to write a recursive function counting(5) that prints 5 4 3 2 1 0 1 2 3 4 5.
I have made two functions down below that do half part each but I need them to be put together.
def countdown(n):
if n == 0:
print 0
else:
print n,
countdown(n-1)
def countup(n):
if n >= 1:
countup(n - 1)
print n,
I suppose the trick is to understand the recursion point does not end execution:
def count_down_up(n):
if not n:
print n # prints 0 and terminates recursion
return
print n # print down 5, 4, 3, 2, 1
count_down_up(n-1) # recursion point
print n # prints up 1, 2, 3, 4, 5
You can see each step print n, <RECURSION>, n, which unfolds to:
5, <count_up_down 4>, 5
5, 4, <count_up_down 3>, 4, 5
# ...
5 ,4, 3, 2, 1, <count_up_down 0>, 1, 2, 3, 4, 5 # recursion stops ...
5, 4, 3, 2, 1, 0, 1, 2, 3, 4, 5
#Reut_Sharabani solution is fine but I think this is simpler to read :
def countdown(N,n):
if abs(n) > N:
return
else:
print(abs(n))
countdown(N,n-1)
Call like this :
countdown(5,5)
One way to do it is by keeping track of 2 lists during the recursion and then stiching them together at return at the end.
def countdown_up(n, i=0, down=[], up=[] ):
if n >i:
return countdown_up(n-1, i, down+[n], [n]+up)
else:
# stich the 2 lists together with the low point [i]
return down+[i]+up
# by default it counts down to 0.
>>>countdown_up(5)
[5, 4, 3, 2, 1, 0, 1, 2, 3, 4, 5]
# you can run with any arbitrary high and low numbers.
>>>countdown_up(10, 3)
[10, 9, 8, 7, 6, 5, 4, 3, 4, 5, 6, 7, 8, 9, 10]
To have the function print instead of return list we just need to change 1 line.
def countdown_up(n, i=0, down=[], up=[] ):
if n >i:
return countdown_up(n-1, i, down+[n], [n]+up)
else:
print(" ".join("%s "%x for x in down+[i]+up))
>>>countdown_up(5)
5 4 3 2 1 0 1 2 3 4 5
>>>countdown_up(10,3)
10 9 8 7 6 5 4 3 4 5 6 7 8 9 10

Android pattern plotting in Python

I need to make make an android pattern or just a pattern in a 3x3 matrix. The pattern is [8, 7, 6, 5, 4, 3, 2, 0, 1] and I need to plot it in a 3x3 matrix. The first entry in the pattern is the beginning point and it connects to the second in the row. The result needs to be the following:
8, 9, 7
6, 5, 4
3, 2, 1
pattern = [8, 7, 6, 5, 4, 3, 2, 0, 1]
matrix = [0,0,0,0,0,0,0,0,0]
lst = ([matrix[i:i + 3] for i in range(0, len(matrix), 3)])
for i in lst:
print(i)
for char in pattern:
matrix[char]=char
Do you mean something like this:
def print_pattern(pattern, cols=3):
for ii, pp in enumerate(pattern):
if ii % cols == 0:
print("")
print(pp),
Then you can call this function as
pattern = [8, 7, 6, 5, 4, 3, 2, 0, 1]
print_pattern(pattern)
This results in the following output:
8 7 6
5 4 3
2 0 1
If you want to print the pattern in the opposite order you can pass a reversed list of your pattern, e.g.:
print_pattern(reversed(pattern))
Gives the following output:
1 0 2
3 4 5
6 7 8
This functions accepts an integer n and an iterable. It makes a list of tuples of width n from that iterable
def mat(n, it):
return list(zip(*[iter(it)]*n))

Categories

Resources