Converting a list that contains integers and strings into a nested tuple, Python [duplicate] - python-3.x

This question already has answers here:
Pairs from single list [duplicate]
(10 answers)
Closed 4 years ago.
I wish to convert a string into a nested tuple for instance:
string = 'Jane A 3 B- 3 F 1#Bob C+ 2 D+ 3#Chris C 4 C 3 C- 2'
As you can see, the string is not normal with # signs and white-spaces in place of a comma. The # sign is what represents the number of names for which I have to compute some data that follows after each name. So I used string.split('#') to create 3 separate strings and from there, I used a for loop to get this on the first iteration:
['A', 3, 'B-', 3, 'F', 1]
The reason why 'Jane' is missing from the list is because I only need to take the values, whether it be a string or an integer, and make a nested tuple out of them. Thus, I wish to convert this list into a nested tuple that looks like:
[('A', 3), ('B-', 3), ('F', 1)]
I will greatly appreciate any help or suggestions.

I dont know if there is a better way, but here we go:
input = ['A', 3, 'B-', 3, 'F', 1]
l1 = input[::2] # get even
l2 = input[1::2] # get odd
tuples = list(zip(l1,l2)) # zip them together
# yes it could be wrote `tuples = list(zip(input[::2],input[1::2]))`
print (tuples)
Output
[('A', 3), ('B-', 3), ('F', 1)]
Try it online!

using regular expressions
>>> import re
>>> [[(mark, int(count))
for mark, count in map(str.split,
re.findall(r'[A-Z][+-]? \d+', student_data))]
for student_data in string.split('#')]
[[('A', 3), ('B-', 3), ('F', 1)],
[('C+', 2), ('D+', 3)],
[('C', 4), ('C', 3), ('C-', 2)]]
Step-by-step explanation
We're separating students (let's call them so) from each other since we need to store their "marks" (or what does these A/B/C/D with +/- mean?) in different containers:
string.split('#')
For each student we're searching "mark" data using regular expression
[A-Z][+-]? \d+
which can be read like
any capital Latin letter (which optionally may be followed by + or - sign) and a whitespace followed by digits
and pass it and student's substring to re.findall function. After that we will have something like:
>>> [re.findall(r'[A-Z][+-]? \d', student_data) for student_data in string.split('#')]
[['A 3', 'B- 3', 'F 1'], ['C+ 2', 'D+ 3'], ['C 4', 'C 3', 'C- 2']]
Finally we can use str.split method to separate letters with +/- from digits and iterate over this pairs converting second coordinates to int.
Further reading
map built-in docs.
re module docs.

Related

How to convert a 3 column tuple without header to a two key single value dictionary in python?

Suppose I have two tuples, say:
l = (water, lily , 6)
m = (history , book, 5)
I want to convert it to a dictionary with 2 keys and a single value.
dict = {(water,lily): 6} {(history, book) : 5}
for the multiple line tuples in python.
How would I accomplish that?
You can use list comprehension.
l = [('water', 'lily' , 6), ('history' , 'book', 5)]
x = {(one, two): three for one, two, three in l}
print(x) # Prints {('water', 'lilly'): 6, ('history', 'book'): 5)}

Python List Comprehension Loop Over Multiple Collections

Say I'm trying to generate a list like this using a comprehension:
[('a', 1), ('b', 2), ('c', 3), ('d', 4)]
I'm receiving an error "TypeError: 'bool' object is not iterable" when trying to do:
mylist = [(letter,num) for letter in 'abcd' and num in range(1,4)]
What am I missing?
This might help:
mylist = [letter for letter in zip('abcd' , range(1,5))]
Or If you want the length to be dynamic.
myString = "abcd"
lengthOfStr= len(myString )
mylist = [letter for letter in zip(myString , range(1,lengthOfStr))]
We here zip two iterables and zip itself return tuple.
You're missing quite a few things actually.
range(1,4) generates the following numbers : 1,2,3
why do you think you should connect the lists using "and"?
and finally, you are missing zip

3Sum using python3 and enumarate

I want to solve the following task using 'enumerate' in python3
The way enumerate works is demonstrated below
nums=(2,7,1,15) # a tuple
for num in enumerate(nums):
print(num, 'hello')
#output
#(0, 2) hello #enumarate(nums) = (0,2)
#(1, 7) hello
#(2, 1) hello
#(3, 15) hello
for count, num in enumerate(nums):
print(num, 'hello')
# Output
#2 hello here count=0 but not displayed
#7 hello here count=1 but not displayed
#1 hello here count=2 but not displayed
#15 hello here count=3 but not displayed
Using the above principle, given an array nums of n integers, are there elements a, b, c in nums such that a + b + c = target sum? Find all unique triplets in the array which gives the sum = target sum.
A solution set for target sum =10 is:
[
[0,1,2]
]
where num at 0th index+num at 1st index+num at 2nd index(7+2+1=10).
Do you have an idea for an algorithm to solve the problem?
I would probably do something like build up two dicts listing all the ways to use the array indexes make a sum with 1 number and 2 numbers to be a certain key value.
E.g., if I had been given nums = [2, 7, 1, 2, 3], I would write code to build up a table like:
one_sum = {1: [2],
2: [0, 3],
3: [4],
7: [1]}
I would use a defaultdict from collections module to efficiently write this code (initialized as one_sum = defaultdict(list) above, though a set would also be a valid data structure for the problem).
It would be straightforward to use enumerate for this part; e.g.,
for i, n in enumerate(nums):
one_sum[n].append(i)
Then I would then build up a two_sum table this time showing all pairs of indexes that make a certain sum. Continuing with the example above, I would want to generate:
two_sum = {3: [(0, 2), (2, 3)],
4: [(2, 4)],
5: [(0, 4), (3, 4)],
8: [(1, 2)],
9: [(0, 1), (1, 3)],
10: [(1, 4)]}
(Note one way to efficiently do this is to loop through the built up one_sum, but be careful not to re-use an index e.g., don't add (2,2) or (4,4) to two_sum[4] because while nums[2] + nums[2] does add up to 4, it uses an index twice (so isn't unique). Also be careful not to double add indexes that are out of order.)
Finally I would loop through the one_sum dict, looking at indices that sum to k and then look in two_sum to see if there are any pairs of indices that sum to target-k, and if so then join the pairs together (checking to sort indices and not repeat indices in a tuple) having found a solution.
For a target of 10 this would ideally build up
three_sum = [(0,1,2), (1,2,3)]
# Note both were added from combining one_sum[1] with two_sum[9]
# nothing from combining one_sum[2] with two_sum[8] as they reuse indexes
# nothing from combining one_sum[3] as two_sum[7]==[]
# nothing new from combining one_sum[7] with two_sum[3] as (0,1,2) and (1,2,3) already present.
Here's a brute force method. It's not as efficient as this algorithm can be, mind you.
def f(nums, target):
sols = []
for i1, n1 in enumerate(nums):
for i2, n2 in enumerate(nums[i1+1:]):
for i3, n3 in enumerate(nums[i2+1:]):
if (n1 + n2 + n3 == target):
sols.append([i1, i2, i3])
return sols

How to add a pair to a dictionary in python?

I created the following dictionary: d = {}
I add to it a new key and a couple as the corresponding d['Key1'] = (1, 2)
If I print the dictionary
{ 'Key1': (1, 2) }
How can I add another pair of integers to the following dictionary to the following key in order to have
{ 'Key1': (1, 2), (1, 3), (1, 4)}
Is it possible to do it in Python? if yes How can I do it?
Can I also count the number of values that correspond to a specific key?
Yes its possible but you need to use a container for your values.
For example you can use a list,also you can use dict.setdefault method for assignment if your keys will have a multiple values, this is useful of you want to add another key with multiple values :
>>> d = {}
>>> d.setdefault('Key1',[]).append((1,2))
>>> d
{'Key1': [(1, 2)]}
>>> d['Key1'].append((1, 3))
>>> d
{'Key1': [(1, 2), (1, 3)]}
>>> d.setdefault('Key2',[]).append((4,2))
>>> d
{'Key2': [(4, 2)], 'Key1': [(1, 2), (1, 3)]}
setdefault(key[, default])
If key is in the dictionary, return its value. If not, insert key with a value of default and return default. default defaults to None.
That's only possible if you make the initial entry a list.
D['key'] = []
D['key'].append((1,2))
D['key'].append((3,4))
{'Key': [(1,2), (3,4)] }
You can't do it directly; in other words, a dict can't hold multiple values associated with the same key. You would need to have a dict of lists.
If the set of keys isn't known in advance, you might want to use a defaultdict, which will automatically create a list (or whatever) each time you access a key which doesn't already exist in the dictionary.
d = collections.defaultdict(list)
To add elements, you would use
d['Key1'].append((1, 2))
instead of
d['Key1'] = (1, 2)
This lets you avoid writing special code to handle the first insertion with a given key.

How to find the number value set to a specific character within a string (without counting) in python [duplicate]

This question already has answers here:
How to find all occurrences of an element in a list
(18 answers)
How to find all occurrences of an element in a list?
(2 answers)
Closed 9 years ago.
I recently got a project in which I need to find all of the indices where a specific character appeared in a string inputted by the user.
For example the user inputs the string "This is a test" and I wanted to find the indices of all the t's in the string I would get 0, 11, 14
I looked through the built in commands and couldn't find anything so it would be a real help to know a method to find this.
Use enumerate and a list comprehension:
st="This is a test"
print([i for i, c in enumerate(st) if c.lower()=='t'])
Or:
print([i for i, c in enumerate(st) if c in 'tT'])
In either case, prints:
[0, 10, 13]
Explanation
First thing that 'makes this work' is that strings are iterable in Python:
>>> st="This is a test"
>>> for c in st:
... print c
...
T
h
i
s
i
s
a
t
e
s
t
Second thing that makes this work is enumerate which adds a count of all the characters in the string as a tuple:
>>> for tup in enumerate(st):
... print tup
...
(0, 'T')
(1, 'h')
(2, 'i')
(3, 's')
(4, ' ')
(5, 'i')
(6, 's')
(7, ' ')
(8, 'a')
(9, ' ')
(10, 't')
(11, 'e')
(12, 's')
(13, 't')
Pulling those two concepts together into a list comprehension produces the result:
[i for i, c in enumerate(st) if c.lower()=='t']
^^^ Produces the tuple of index and character
^ ^ Index, Character
^^^^^^^^^^^ test the character if it is 't'
^ What is wanted - list of indices
Just a straightforward approach as an alternative to a (better) enumerate option:
[range(len(st))[i] for i in range(len(st)) if st[i].lower() == 't']

Resources