Count occurrences of an element in list - python

I know that there are already a lot of questions about this specific topic, but I can't find a proper solution for my problem.
I have the input:
2, 20, 15, 16, 17, 3, 8, 10, 7
I want to see if there are 'double' numbers in my code. I have tried working with this code.
lijst = input('Give a list: ')
teller = 0
for i in lijst.split(','):
if lijst.count(i) != 1:
teller += 1
print(teller != 0)
Normally I should get False, since there are no double numbers in the given list. However, I recieve True. I suggest that's because the 2 appears also in 20.
True
Does anyone know how to avoid this problem, so the the '2' isn't counted twice?

You can use collections.Counter which does exactly that
>>> data = [2, 20, 15, 16, 17, 3, 8, 10, 7]
>>> from collections import Counter
>>> Counter(data)
Counter({2: 1, 3: 1, 7: 1, 8: 1, 10: 1, 15: 1, 16: 1, 17: 1, 20: 1})
>>>
It counts number of occurences and returns a dict with keys indicates the item, and value is number of occurences.
If you just need to know if there are duplicates or not, regardless of which item is the duplicate, you can simply use Set over your list and check len() afterwards:
len(data) == len(set(data))

You can compare the length of the input with the length of the set of unique elements in input:
def has_repeated_elements(input):
"""returns True if input has repeated elements,
False otherwise"""
return len(set(input)) != len(input)
print(not has_repeated_elements(input))

Related

push values from a python dictionary to corresponding key-values of a second dictionary

I have two dictionaries in a program I'm writing for fun to get practice dealing with .jsons in Python. I want my program to take any player's .json file (actually pretty easy to obtain) and output how many runes of each rune type the player owns. It's basically my first week of learning about data in Python (or any language) so I'm still very new to this.
The first dictionary, I created like this:
rune_set_counts = {}
for i in range(1, 24):
rune_set_counts[i] = 0
I made the range begin with 1 because the game's .json indexes rune sets using values from 1 to 23.
The second dictionary contains 23 keys, and each key is the string that is the actual name of that particular rune type in the game. So, for example, in rune_set_counts, the first key is 1. In my second dictionary, rune_set_translated_counts, the first key is the corresponding name, "Energy".
I would like to make a function that transposes the values from the first dictionary to the second dictionary. If rune_set_counts[1] = 5, I want rune_set_translated_counts[Energy] = 5.
This was my attempt at a function:
def convert_to_rune_set(old_dict, new_dict):
for i in range(len(old_dict)):
frequency = old_dict[i+1]
new_dict[i] = frequency
The problem is, I tried that and it just added all 23 key-value pairs from the old dictionary to the new one, lol. I don't want 46 keys. How should I do this?
As #Tim Roberts mentioned in his answer, Dictionary does not have order, you will need a map of number vs their names in rune. Try something like this.
from random import randint
rune_set_counts = {}
for i in range(1, 24):
rune_set_counts[i] = randint(0, 10)
print(rune_set_counts)
# prints {1: 0, 2: 0, 3: 6, 4: 5, 5: 0, 6: 4, 7: 3, 8: 0, 9: 2, 10: 7, 11: 6, 12: 7, 13: 7, 14: 4, 15: 4, 16: 6, 17: 4, 18: 0, 19: 4, 20: 10, 21: 0, 22: 5, 23: 2}
rune_name_map = {
1: "Energy",
2: "A",
3: "B",
# And so on upto 23. You need to create this map hard-coded or read from a json
23: "V"
}
def convert_to_rune_set(count_map, name_map):
new_count_map = {}
for i in range(1, 24):
new_count_map[name_map[i]] = count_map[i]
# name_map[i] gives the name mapped to that number
return new_count_map
new_map = convert_to_rune_set(rune_set_counts, rune_name_map)
print(new_map)
#prints {'Energy': 0, 'A': 0, 'B': 6, 'C': 5, ......., 'V': 2}
If ALL you want to is swap the keys and values, that is like this:
def convert_to_rune_set(old_dict, new_dict):
for k,v in old_dict.items()
new_dict[v] = k
However, in your description, I don't understand where "Energy" comes from. Remember, dictionaries do not have "order". You can't refer to the 3rd entry in a dictionary. Perhaps you need a list of names to keep things straight?

How to make two dimensional list using an existing one dimensional list for hashing?

I have a list of integers like: [10, 20, 50, 30] and I want to count the occurrence of these integers in another list.
For example if 10 in the first list comes twice in the second list with rest of the integers occuring only once, then the output must be: [[10:2], [20:1], [50:1], [30:]]
I tried with the below code but I'm getting an error: AttributeError: 'int' object has no attribute 'extend'. What am I doing wrong ?
for i in range(0,len(s)):
s[i].append([])
for j in range(0,len(ar)):
if s[i]==ar[j]:
s[i][0]+=1
I am trying to achieve a sort of hash map, please share any better approach you may have. Thank you!
A Counter object is ideally suited for the task.
from collections import Counter
wanted = [10, 20, 50, 30]
other_list = [10, 20, 10, 40, 60, 50, 100, 70]
wanted_set = frozenset(wanted)
counts = Counter([number for number in other_list if number in wanted_set])
print(counts)
# Access the count for every number.
for number in counts:
print('{0}: {1}'.format(number, counts[number]))
You can use both Dictionary comprehension in Python:
s = [10, 20, 50, 30]
{curr: s.count(curr) for curr in s}
Out[0]: {10: 1, 20: 1, 50: 1, 30: 1}
You can also use Python collection Counter like this:
from collections import Counter
Counter(s)
Out[0]: Counter({10: 1, 20: 1, 50: 1, 30: 1})
References:
List and Dictionary Comprehension in Python - here
Counter object documentation - here
Good Luck!

Turning a string of integers into a list and sorting it by odd and even elements

I have a string of integers, such as string = {11, 2, 14, 1, 17, 1, 123, 1} What I need to do is turn it into a list, and then sort them into two separate lists of odd and even elements.
I had a dictionary that looked like {11: 2, 14: 1, 17: 1, 123: 1}, converted it to a string, and removed the colons into commas, so now I have the first string. I did this so I can split up the elements into having the numbers 11, 14, 17, and 123 in one list, and 2, 1, 1, and 1 in the other list.
I think I can convert this string into a list, and then use a loop to append each element into the list I need it to be. The problem is, I can't figure out how to turn this string into a list again. How would I do that? Alternatively, can I split the values the way I want straight from the dictionary and save steps? Thanks for any help
Yes, you can split the values straight from the dictionary! You'd use the .keys() and .values() on the dictionary object.
>>> obj = {11: 2, 14: 1, 17: 1, 123: 1}
>>> list(obj.keys())
[123, 17, 11, 14]
>>> list(obj.values())
[1, 1, 2, 1]
String conversion isn't necessary. In fact, there's no need to create a list of all keys for your problem. You can use collections.defaultdict and iterate your dictionary:
from collections import defaultdict
x = {11: 2, 14: 1, 17: 1, 123: 1}
dd = defaultdict(list)
for key in x:
dd['odd' if key % 2 else 'even'].append(key)
The result is a dictionary mapping of odd and even keys:
defaultdict(list, {'odd': [11, 17, 123],
'even': [14]})
You can then access odd keys via dd['odd'], even keys via dd['even'].
To split a string into ints, use the built-in split method to return a list of each of the items:
new_list = string.split(", ")

using += to populate a list through while loop gives me an error

I have a very basic understanding that += and .append are quite similar in terms of appending new element to a list. However, I find them perform differently when I try to populate a list with random integer values through while loop. append works well, however, running my program with += will give me an error :
TypeError: 'int' object is not iterable
Here is my code:
1.use +=
import random
random_list = []
list_length = 20
# Write code here and use a while loop to populate this list of random integers.
i = 0
while i < 20:
random_list += random.randint(0,10)
i = i + 1
print random_list
**TypeError: 'int' object is not iterable**
2.use .append
import random
random_list = []
list_length = 20
# Write code here and use a while loop to populate this list of random integers.
i = 0
while i < 20:
random_list.append(random.randint(0,10))
i = i + 1
print random_list
**[4, 7, 0, 6, 3, 0, 1, 8, 5, 10, 9, 3, 4, 6, 1, 1, 4, 0, 10, 8]**
Does anyone know why would this happen?
This happens because += is for appending a list to the end of another list, not for appending an item.
It is the short version of doing:
items = items + new_value
If new_value isn't a list this will fail because you can't use + to add a item to a list.
items = items + 5 # Error: can only add two list together
The solution is to make the value into a one-item long list:
items += [value]
Or to use .append - the preferred way to add single items to a list.
Yes, it's tricky. just add a , at end of random.randint(0, 10)
import random
random_list = []
list_length = 20
# Write code here and use a while loop to populate this list of random integers.
i = 0
while i < 20:
random_list += random.randint(0, 10),
i += 1
print random_list
It will print:
[4, 7, 7, 10, 0, 5, 10, 2, 6, 2, 6, 0, 2, 7, 5, 8, 9, 8, 0, 2]
You can find more explanation about trailing ,

Python finding repeating sequence in list of integers?

I have a list of lists and each list has a repeating sequence. I'm trying to count the length of repeated sequence of integers in the list:
list_a = [111,0,3,1,111,0,3,1,111,0,3,1]
list_b = [67,4,67,4,67,4,67,4,2,9,0]
list_c = [1,2,3,4,5,6,7,8,9,0,1,2,3,4,5,6,7,8,9,0,23,18,10]
Which would return:
list_a count = 4 (for [111,0,3,1])
list_b count = 2 (for [67,4])
list_c count = 10 (for [1,2,3,4,5,6,7,8,9,0])
Any advice or tips would be welcome. I'm trying to work it out with re.compile right now but, its not quite right.
Guess the sequence length by iterating through guesses between 2 and half the sequence length. If no pattern is discovered, return 1 by default.
def guess_seq_len(seq):
guess = 1
max_len = len(seq) / 2
for x in range(2, max_len):
if seq[0:x] == seq[x:2*x] :
return x
return guess
list_a = [111,0,3,1,111,0,3,1,111,0,3,1]
list_b = [67,4,67,4,67,4,67,4,2,9,0]
list_c = [1,2,3,4,5,6,7,8,9,0,1,2,3,4,5,6,7,8,9,0,23,18,10]
print guess_seq_len(list_a)
print guess_seq_len(list_b)
print guess_seq_len(list_c)
print guess_seq_len(range(500)) # test of no repetition
This gives (as expected):
4
2
10
1
As requested, this alternative gives longest repeated sequence. Hence it will return 4 for list_b. The only change is guess = x instead of return x
def guess_seq_len(seq):
guess = 1
max_len = len(seq) / 2
for x in range(2, max_len):
if seq[0:x] == seq[x:2*x] :
guess = x
return guess
I took Maria's faster and more stackoverflow-compliant answer and made it find the largest sequence first:
def guess_seq_len(seq, verbose=False):
seq_len = 1
initial_item = seq[0]
butfirst_items = seq[1:]
if initial_item in butfirst_items:
first_match_idx = butfirst_items.index(initial_item)
if verbose:
print(f'"{initial_item}" was found at index 0 and index {first_match_idx}')
max_seq_len = min(len(seq) - first_match_idx, first_match_idx)
for seq_len in range(max_seq_len, 0, -1):
if seq[:seq_len] == seq[first_match_idx:first_match_idx+seq_len]:
if verbose:
print(f'A sequence length of {seq_len} was found at index {first_match_idx}')
break
return seq_len
This worked for me.
def repeated(L):
'''Reduce the input list to a list of all repeated integers in the list.'''
return [item for item in list(set(L)) if L.count(item) > 1]
def print_result(L, name):
'''Print the output for one list.'''
output = repeated(L)
print '%s count = %i (for %s)' % (name, len(output), output)
list_a = [111, 0, 3, 1, 111, 0, 3, 1, 111, 0, 3, 1]
list_b = [67, 4, 67, 4, 67, 4, 67, 4, 2, 9, 0]
list_c = [
1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2,
3, 4, 5, 6, 7, 8, 9, 0, 23, 18, 10
]
print_result(list_a, 'list_a')
print_result(list_b, 'list_b')
print_result(list_c, 'list_c')
Python's set() function will transform a list to a set, a datatype that can only contain one of any given value, much like a set in algebra. I converted the input list to a set, and then back to a list, reducing the list to only its unique values. I then tested the original list for each of these values to see if it contained that value more than once. I returned a list of all of the duplicates. The rest of the code is just for demonstration purposes, to show that it works.
Edit: Syntax highlighting didn't like the apostrophe in my docstring.

Categories