only update key in dictionary from another dictionary as reference - python-3.6

For simplicity, i have 2 dictionaries below. i want to update the second dictionary (but only the keys) and set the value to 0 in reference to the first dictionary.
original dictionaries:
dict1={'a': 1, 'b': 2, 'c': 3}
dict2 ={'a': 2, 'b': 2}
after update:
dict1 ={'a': 1, 'b': 2, 'c': 3}
dict2 ={'a': 2, 'b': 2, 'c': 0}

You can use dict2.update with a dict comprehension to do this:
dict1={'a': 1, 'b': 2, 'c': 3}
dict2 ={'a': 2, 'b': 2}
dict2.update({k:0 for k,v in dict1.items() if k not in dict2})
print (dict1)
print (dict2)
{'a': 1, 'b': 2, 'c': 3}
{'a': 2, 'b': 2, 'c': 0}

Related

Multi-line text input to dictionary

Say I've got a multi-line input from a text file that looks smth like this:
(empty string here)
1 -30 2 0
3 0 5 10
etc.
I parsed the input and formed a list out of it:
lst = [[], [(1, -30), (2, 0)], [(3, 0), (5, 10)]]
Assume I want to make a dictionary where the key is the line number (starting with 1) and the value is a nested dictionary which contains the first element of a tuple as a key and the second one as a value:
**lst -> dict:**
dict = {'1': {}, '2': {1: -30, 2: 0}, '3': {3: 0, 5: 10}}
What's the best (pythonic) way to do this? Spent couple hours by now trying to do this.
Thanks!
lst = [[], [(1, -30), (2, 0)], [(3, 0), (5, 10)]]
print( {str(i): dict(v) for i, v in enumerate(lst, 1)} )
Prints:
{'1': {}, '2': {1: -30, 2: 0}, '3': {3: 0, 5: 10}}

Measure of Dispersion for Labelled Data

I have data of the form {'A': 5, 'B': 10, 'C': 3} and I'd like to compute a value that's between 0 and 1 for the level of dispersion between labeled data. For example, if all the data were of the form {'A':3}, then there would be no dispersion and the value computed would be 0. If the data were of the form {'A': 1, 'B': 1, 'C': 1}, then the value computed would be 1 because there is maximal dispersion between the labels. And finally if the data were of the form {'A': 1, 'B': 2} then the value computed would be somewhere between 0 and 1.
More specifically, I'm trying to compute a value that indicates the level of physical dispersion between offices. For example, if a team of 10 people are in a single office, then there's no dispersion. If they're in a 10 different offices, then there's maximal dispersion. {'A': 2, 'B': 2, 'C': 2} should have a value less than {'A': 1, 'B': 1, 'C': 1, 'D': 1, 'E': 1, 'F': 1} because the latter is more disperse.
What's the correct mathematical function for this?

From a list of ints extract all consecutive repetitions in a list of lists

Extract all consecutive repetitions in a given list:
list1 = [1,2,2,3,3,3,3,4,5,5]
It should yield a list like this
[[2,2],[3,3,3,3],[5,5]]
I tried the code below. I know it is not the proper way to solve this problem but I could not manage how to solve this.
list1 = [1,2,2,3,3,3,3,4,5,5]
list2 = []
for i in list1:
a = list1.index(i)
if list1[a] == list1[a+1]:
list2.append([i,i])
print(list2)
You can use this to achieve it. There are "easier" solutions using itertools and groupby to get the same result, this is how to do it "by hand":
def FindInnerLists(l):
'''reads a list of int's and groups them into lists of same int value'''
result = []
allResults = []
for n in l:
if not result or result[0] == n: # not result == empty list
result.append(n)
if result[0] != n: # number changed, so we copy the list over into allResults
allResults.append(result[:])
result = [n] # and add the current to it
# edge case - if result contains elements, add them as last item to allResults
if result:
allResults.append(result[:])
return allResults
myl = [2, 1, 2, 1, 1, 1, 1, 2, 2, 2, 1, 2, 7, 1, 1, 1,2,2,2,2,2]
print(FindInnerLists(myl))
Output (works for 2.6 and 3.x):
[[2], [1], [2], [1, 1, 1, 1], [2, 2, 2], [1], [2], [7], [1, 1, 1], [2, 2, 2, 2, 2]]
Another way to do it:
list1 = [1, 2, 2, 3, 3, 3, 3, 4, 5, 5]
result = [[object()]] # initiate the result with object() as a placeholder
for element in list1: # iterate over the rest...
if result[-1][0] != element: # the last repeated element does not match the current
if len(result[-1]) < 2: # if there was less than 2 repeated elements...
result.pop() # remove the last element
result.append([]) # create a new result entry for future repeats
result[-1].append(element) # add the current element to the end of the results
if len(result[-1]) < 2: # finally, if the last element wasn't repeated...
result.pop() # remove it
print(result) # [[2, 2], [3, 3, 3, 3], [5, 5]]
And you can use it on any kind of a list, not just numerical.
This would work:
list1 = [1,2,2,3,3,3,3,4,5,5]
res = []
add = True
last = [list1[0]]
for elem in list1[1:]:
if last[-1] == elem:
last.append(elem)
if add:
res.append(last)
add = False
else:
add = True
last = [elem]
print(res)
Output:
[[2, 2], [3, 3, 3, 3], [5, 5]]

How to generate a list of certain subsets of x in r?

I want to generate a set in r which contains all of its subsets but not the set itself.
For example, say I have the set
{1, 2, 3}
I want to generate the following list in r
{{}, {1}, {2}, {3}, {1, 2}, {1, 3}, {2, 3}}
However, the commands I am trying in r (powerset and set_power) are giving
{{}, {1}, {2}, {3}, {1, 2}, {1, 3}, {2, 3}, {1, 2, 3}}
I want to create a set which contains all of it's subsets.
Any help would be appreciated!
You can use the sets package.
First, create set A:
library(sets)
A <- set(1,2,3)
A
{1, 2, 3}
Find the power set:
PS <- 2^A
PS
{{}, {1}, {2}, {3}, {1, 2}, {1, 3}, {2, 3}, {1, 2, 3}}
And substract A from the power set:
B <- set_symdiff(PS,set(A))
B
{{}, {1}, {2}, {3}, {1, 2}, {1, 3}, {2, 3}}
I have managed to do it by
s <- c(1,2,3)
powerSet(s)[-length(powerSet(s))]
Thanks!

Searching matrices in Mathematica 8 - Trying to find other elements on the same row as X

The text in italics describes my general goal, if anyone is interested. Question is underneath.
I am trying to graph the energy levels of simple molecules using Mathematica 8. My method is crude, and goes as this:
Find eigenvalues of simple Hückel matrix.
Delete duplicates and determine size of list.
Evaluate the number of degeneracies by comparing duplicate list with no-duplicate list.
Create a n x 2 zero matrix where n is the number of unique energy levels.
5. Fill first column with unique energy levels, second column with degeneracies.
The matrix generated in step 5 can look like this:
(1 2)
(3 1) == M
(-1 1)
I wish to evaluate the maximum of column 2, and then find the value of the element in the same row, but in column 1. In this case, the answer I am looking for is 1.
These commands both evaluate to -1:
Extract[M[[All, 1]], M[[Max[M[[All, 2]]], 1]]]
M[[Max[M[[All, 1]]], 1]]
which is not the answer I want.
Any tips?
EDIT: This
Part[Part[Position[M, Max[M[[All, 2]]]], 1], 1]
works, but I don't understand why I have to use Part[] twice.
m = {{1, 2}, {3, 1}, {-1, 1}}
max = Max[m[[All, 2]]]
So find the position of the max and replace the second column with the first:
pos=Position[m, max] /. {x_,_}:>{x,1}
{{1,1}}
Then take the first element from pos, i.e. {1,1} and sub use it in Part
m[[Sequence ## First[pos]]]
1
But having said that I prefer something like this:
Cases[m, {x_, max} :> x]
{1}
The result is a list. You could either use First#Cases[...] or you might want to keep a list of results to cover cases where the maximum value occurs more than once in a column.
The inner Part gives you the first occurance of the maximum. Position returns a list of positions, even if there is only one element that has the maximum value, like this:
M = {{2, 2}, {2, 3}, {2, 2}, {1, 1}}
{{2, 2}, {2, 3}, {2, 2}, {1, 1}}
Position[M, Max[M[[All, 2]]]]
{{2, 2}}
So you want the first element in the first element of this output. You could condense your code like this:
Position[M, Max[M[[All, 2]]]][[1, 1]]
However, one thing that I think your code needs to handle better is this case:
M = {{3, 2}, {2, 3}, {2, 2}, {1, 1}}
3, 2}, {2, 3}, {2, 2}, {1, 1}}
Position[M, Max[M[[All, 2]]]]
{{1, 1}, {2, 2}}
You will get the wrong answer with your code in this case.
Better would be:
M[[All, 1]][[Position[M[[All, 2]], Max[M[[All, 2]]]][[1, 1]] ]]
Or alternatively
M[[Position[M[[All, 2]], Max[M[[All, 2]]]][[1, 1]], 1]]
If you only want a single column one value in the case of duplicate maximum values in column two I suggest that you make use of Ordering:
m = {{1, 3}, {1, 8}, {5, 7}, {2, 2}, {1, 9}, {4, 9}, {5, 6}};
m[[ Ordering[m[[All, 2]], -1], 1 ]]
{4}

Resources