How to find the product of a value * the unique number of times it occurs in a list? - python-3.x

Example if i have a list
[100,50,1,1,1,1]
I want it to output
100 * 1 + 5 * 1 + 1 * 4
Currently Im using a dictionary to do so.
lst = [100, 50, 1, 1, 1, 1, 100]
total = 0
dic = {}
for elem in lst:
if not elem in dic:
dic[elem] = total
#print(dic)
else:
dic[elem] += total + 1
output is alittle off
{100: 1, 50: 0, 1: 3}
100 actually comes twice, and 1 appears 4 times.

So to get how many times you need to multiply each number, you can use the count method.
Knowing that, the problem then becomes looping through unique elements in the original list and then counting/multiplying them from the original list.
To get unique values, we can use a set!
lst = [100, 50, 1, 1, 1, 1, 100]
unique, sum = set(lst), 0
for number in unique:
sum += number * lst.count(number)
print(sum)
If you actually need the dictionary:
lst = [100, 50, 1, 1, 1, 1, 100]
unique, unique_counts = set(lst), {}
for number in unique:
unique_counts[number] = lst.count(number)
print(unique_counts)

Related

How do you append a value to a list by a certain frequency?

I'm writing a program to analyse a frequency table with different functions (mean, median, mode, range, etc) and I have the user inputting their data in two lists and then converting those answers into lists of integers
values_input = input('First, enter or paste the VALUES, separated by spaces (not commas): ')
freq_input = input('Now enter the corresponding FREQUENCIES, separated by spaces: ')
values = values_input.split()
freq = freq_input.split()
data_list = []
For every value, I want the program to append it to data_input by the corresponding frequency.
For example (desired result):
If values was: 1 2 3 4
and frequency was: 2 5 7 1
I want data_list to be:
[1, 1, 2, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, 4]
At the moment I have this:
for i in range(len(values)):
j = 3
while j != 0:
data_input.append(values[i])
j -= 1
But that only appends the values to data_input 3 times instead of the frequency
a = input("First, enter or paste the VALUES, separated by spaces (not commas): ").split()
b = input("Now enter the corresponding FREQUENCIES, separated by spaces: ").split()
a = [int(i) for i in a]
b = [int(i) for i in b]
x = []
y = 0
for elem in a:
temp = []
temp.append(elem)
x.append(temp * b[0+y])
y += 1
final = []
for lst in x:
for elem in lst:
final.append(elem)
print(final)
I am also a newbie. I know there are more efficient ways, but for now I have come up with this.
You can use list multiplication to create a list of each value with the appropriate frequency. zip the two lists together to get the matching values for each index:
values = [1,2,3,4]
freq = [2,5,7,1]
result = []
for v, f in zip(values, freq):
result += [v] * f
Output:
[1, 1, 2, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, 4]

the terminal doesn't display when i compile the code

I want to create a program, such that it returns the index of the element, if each element in list 1 matches the corresponding element in list 2
for example: [5, 1, -10, 3, 3], [5, 10, -10, 3, 5].
Here 5 in list 1 matches the first element 5 in list 2 hence it returns index 0. similarly -10 matches with -10. hence gives index 2.
required output
[0,2,3]
MY CODE:
def same_values(lst1,lst2):
n = 1
lst_of_index = []
while(n <= len(lst1)):
for i in lst1:
value_1 = i
for j in lst2:
value_2 = j
if (value_1 == value_2):
indexed_value = lst1.index(i)
lst_of_index.append(indexed_value)
n += 1
return lst_of_index
print(same_values([5, 1, -10, 3, 3], [5, 10, -10, 3, 5]))
when i run the code, it doesn't display anything. Is something wrong with my code?
Combining the answers from #user12137152 and #diego-mourino with a list comprehension, you get a relatively simple one liner:
def same_values(lst1,lst2):
return [idx for idx, val in enumerate(zip(lst1, lst2)) if val[0] == val[1]]
Use a for loop and zip to iterate over both the lists at the same time. The benefit of the following program is that it doesn't crashes even if the lists are of different sizes.
def same_values(lst1, lst2):
lst_of_index = []
n = 0
for i, j in zip(lst1, lst2):
if i == j:
lst_of_index.append(n)
n += 1
return lst_of_index
print(same_values([5, 1, -10, 3, 3], [5, 10, -10, 3, 5]))
The function you implementate has a major bug. The function doesn´t return anything because you are generating an infinite loop. That`s because you first iterate over all the values of the lists and, after that, you compare value_1 and value_2. In this example, the value_1 and value_2 will be 3 and 5 respectively (because you are comparing the last value of the lists because the if statement is after the two iterators over the lists at the same indentation level). And because of that, the while loop gets stuck.
I propose to you an alternative implementation, using enumerate() instead of a the while. When you use enumerate over a list, this iterator give you 2 elements: the position of a given element of the list (i) and the element of the list (in this case, value_1). This implementation is shown below:
def same_values(lst1,lst2):
lst_of_index = []
for i, value_1 in enumerate(lst1):
value_2 = lst2[i]
if (value_1 == value_2):
lst_of_index.append(i)
return lst_of_index

Counting instances of N in an array using Recursion in Python

I would like to count the number of instances of a given number N in an array using recursion. For example, given:
array = [1, 2, 3, 1, 1, 4, 5, 2, 1, 8, 1]
and N = 1, the function should return 5.
This problem can be solved using the .counter attribute as shown here. However, I am looking to not use any in-built functions or attributes.
Here's my attempt to solve this using recursion but I get a count of 1 and not 5. What am I doing wrong?
def count_val(array, n, count=0):
if len(array) == 0:
return None
# Base Case
if len(array) == 1:
if array[0] == n:
count += 1
else:
count_val(array[1:], n, count)
if array[0] == n:
count += 1
return count
print(count_val2(array, 1))
1
I think for an empty array, the value should be 0 (len == 0 should be the base case), and, you don't need to have a count parameter if you just return the count, your function could be reduced to this:
def count_val(array, n):
if len(array) == 0:
return 0
return (array[0] == n) + count_val(array[1:], n)
array = [1, 2, 3, 1, 1, 4, 5, 2, 1, 8, 1]
print(count_val(array, 1))
Output:
5
You can have it as a one-liner as well (as suggested by #blhsing):
def count_val(array, n):
return len(array) and (array[0] == n) + count_val(array[1:], n)
What am I doing wrong?
The function you wrote will always keep only the last few characters, so after a while it will be [1, 8, 1], after that [8, 1] and after that [1], which returns 1. The array never contains just any of the other 1s.
An easy way to do this is to loop over all elements in a list and test if they are equal to N.
array = [1, 2, 3, 1, 1, 4, 5, 2, 1, 8, 1]
def count_val(array, n):
if len(array) == 0:
return 0
count=0
for i in array:
if i==n:
count += 1
return count
print(count_val(array, 1))
This returns 5.

How to iterate through a numbered list and every time value 1 appears start over?

Given a list:
list1 = [1,2,3,4,5,6,1,2,3,4,1,2,3,4,5,6,7]
While iterating though list1, every time the integer 1 is hit, start the loop over but increment it by 1.
Tried the two examples below but it only returns a list of 1's for the length of list1.
digit = []
i = 0
for num in list1:
num = i
if num != 1:
i += 1
digit.append(i)
elif num == 1:
digit.append(num)
digit = []
i = 0
for num in list1:
num = i
if num == 1:
digit.append(num)
continue
elif num != 1:
i += 1
digit.append(i)
digit
Looking to get something like the list below
digit = [1,1,1,1,1,1,2,2,2,2,3,3,3,3,3,3,3]
You're overthinking this. Initialise a variable to zero. Append it to a list at each iteration. Increment if the corresponding list value is 1.
values = []
i = 0
for l in list1:
if l == 1: # The check must come before appending. Can you explain why?
i += 1
values.append(i)
values
# [1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3]
If you were to ask me for a pythonic solution to this problem, I'd suggest itertools.accumulate:
from itertools import accumulate
from operator import add
list(accumulate((int(x == 1) for x in list1), add))
# [1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3]

how to fix python fibonacci sequence script?

My assignment is to create a function that produces 3 lists of the numbers in the fibonacci sequence starting at 0. Here is my code so far.
def fibList(n):
a = 0; b = 1; fibList = []
if n <= 0:
return
elif n == 1:
fibList = [a]
elif n == 2:
fibList = [a,b]
else:
for i in range(0,n):
a, b = b, a + b
fibList.append(b)
return fibList
def main():
print (fibList(4))
print (fibList(10))
print (fibList(-4))
what i want my output to look like is [0,1,1,2] for 4, [0,1,1,2,3,5,8,13,21,34,55] for 10, and [] for -4
My issue begins with fibList(4) currently giving an output of [1, 2, 3, 5] and fibList(10) gives an output of [1, 2, 3, 5, 8, 13, 21, 34, 55, 89] and for -4 I get "None" instead of a [].
If I type in fibList(1) I get [0] and for fibList(2) I get [0, 1], but when i test fibList(3) the first 0 and 1 are lost, giving me [1,2,3]
How would I go about making it so any number above 3 starts with [0, 1, 1, 2...]? My main issue is getting the 0 and 1 to be the first two numbers in the sequence and getting fibList(-4) to produce a [].
any help or tips would be greatly appreciated :-)
All that you are missing is to add an empty list in the case of less than or equal to zero, and recurse correctly over your range of Fibonacci numbers greater than 2. Making those small changes like so:
def fibList(n):
if n <= 0:
fibnums = []
elif n == 1:
fibnums = [0]
elif n >= 2:
fibnums = [0, 1]
for i in range(2,n):
fibnums.append(fibnums[i-1]+fibnums[i-2])
return fibnums
Note that this recursive method can get quite slow for large numbers, if that is of concern to you with your program. Best of luck!
With these changes,
print (fibList(4)) => [0, 1, 1, 2]
print (fibList(10)) => [0, 1, 1, 2, 3, 5, 8, 13, 21, 34]
print (fibList(-4)) => []
You did not quite define your function. Should the resulting list have n values [f(0), ..., f(n-1)] or n+1 values [f(0), ..., f(n)]? Your examples are contradictory: the 'expected' output for 4 has 4 values ending with f(3) while that for 10 has 11 values ending with f(10).
I am going to assume that the latter is correct. Here is a revised version of your fast iterative solution. (If my assumption is wrong, stop the range at n instead of n+1.)
def fibs(n):
"Return [fib(0), ..., fib(n)."
ret = [0, 1] # fib(0), fib(1)
a, b = ret
if n <= 1:
return ret[:n+1]
else:
for i in range(2, n+1):
a, b = b, a+b # b = f(i)
ret.append(b)
return ret
print(fibs(-4), fibs(0), fibs(2), fibs(4), fibs(10))
#
[] [0] [0, 1, 1] [0, 1, 1, 2, 3] [0, 1, 1, 2, 3, 5, 8, 13, 21, 34, 55]

Resources