I'm writing a program who's input is a set of sets (or "collection") in python syntax. The output of the program should be the same collection in proper mathematical syntax. To do so, I've written a recursive function
collection = set([
frozenset(["a,b,c"]),
frozenset(),
frozenset(["a"]),
frozenset(["b"]),
frozenset(["a,b"])
])
def format_set(given_set):
# for each element of the set
for i in given_set:
#if the element is itself a set, begin recursion
if type(i) == frozenset:
format_set(i)
else:
return "{", i, "},",
calling format_set(collection) gives the output
{ a,b }, { a,b,c }, { b }, { a },
which is missing a pair of parenthesis, and has an extra comma at the end. The correct output would be
{{ a,b }, { a,b,c }, { b }, { a },{}}.
Thus, I would need to add "{" before the first recursion, and "}" after the last, as well as not adding the comma after the last recursion. Is there a way to find the final recursion?
I could always solve the extra parenthesis problem by defining:
def shortcut(x):
print "{", frozen_set(x), "}"
However, I feel like that's somewhat inelegant, and still leaves the comma problem.
It will be more straightforward if you check the type first and then do the iteration:
def format_set(given):
if isinstance(given, (set, frozenset)):
return '{' + ', '.join(format_set(i) for i in given) + '}'
else:
return str(given)
Output:
{{a,b}, {a,b,c}, {}, {b}, {a}}
Also, note that in your example input all sets are actually empty or have 1 element. If you change the input like this...
collection = set([
frozenset(["a", "b", "c"]),
frozenset(),
frozenset(["a"]),
frozenset(["b"]),
frozenset(["a", "b"])
])
...you'll get this output:
{{a, c, b}, {}, {b}, {a}, {a, b}}
Related
I would like to know the depth of a dict that contains a list of dicts, I wrote a simple code but the problem is that it increment the counter of depth at each step.
this is the input that i have as an example :
respons = {
"root":{
"Flow":[{
"Name":"BSB1",
"Output":[{
"Name":"BSB2",
"Output":[{
"Name":"BSB5",
"Output":[{
"Name":"BSB6",
"Output":[{
"Name":"BSB8",
"Output":[]
}]
},
{
"Name":"BSB7",
"Output":[]
}]
}]
},
{
"Name":"BSB3",
"Output":[{
"Name":"BSB4",
"Output":[]
}]
}]
}]
}
}
def calculate_depth(flow,depth):
depth+=1
md = []
if flow['Output']:
for o in flow['Output']:
print(o['BusinessUnit'])
md.append(calculate_depth(o,depth))
print(max(md))
print(md)
return max(md)
else:
return depth
print(calculate_depth(respons['root']['Flow'][0],0))
normally I want the depth of the longest branch of this dict not to go through all of the branches and increment at each step
EDIT
The desired Outcome will be for this structure : 5
Why ?
It is the longest branche BSB1 => BSB2 => BSB5 => BSB6 => BSB8
What the depth is of this structure is debatable. Your code (and the way you indent the data structure) seems to suggest that you don't want to count the intermediate lists as adding a level to a path. Yet if you would want to access deep data you would write
respons['root']['Flow'][0]['Output'][0]['Output'][0]
# ^^^ ^^^ ^^^ ...not a level?
And taking this to the leaves of this tree: is the deepest [] a level?
Here is code that only counts dicts as adding to the level, and only when they are not empty:
def calculate_depth(thing):
if isinstance(thing, list) and len(thing):
return 0 + max(calculate_depth(item) for item in thing)
if isinstance(thing, dict) and len(thing):
return 1 + max(calculate_depth(item) for item in thing.values())
return 0
This prints 19 for the example data:
print(calculate_depth(respons['root']['Flow'][0]))
Adapt to your need.
I am trying to combine all the elements in a list on the basis of some delimiters; I am facing difficulty when the delimiter pair is more than 1.
Say this is the list :
['{','k0c','k1b','k2b','k3b','}','{','\\g0','\\g1','\\g2','\\g3','}']
12 items in this list
Whenever it finds '{' and '}' I want all of the elements within those indexes to be concatenated into one so that it is:
['{ k0c, k1b, k2b, k3b }' , '{\\g0 , \\g1, \\g2, \\g3 }' ]
2 items in this list are what I want with all the elements inside the delimiters turned into one element of the list.
Something like this oughta do the trick:
input_data = [
"{",
"k0c",
"k1b",
"k2b",
"k3b",
"}",
"{",
"\\g0",
"\\g1",
"\\g2",
"\\g3",
"}",
]
lists = []
current_list = None
for atom in input_data:
if atom == "{":
assert current_list is None, "nested lists not supported"
current_list = []
lists.append(current_list)
elif atom == "}":
current_list.append(atom)
current_list = None
continue
assert current_list is not None, (
"attempting to add item when no list active: %s" % atom
)
current_list.append(atom)
for lst in lists:
print(" ".join(lst))
The output is
{ k0c k1b k2b k3b }
{ \g0 \g1 \g2 \g3 }
but you can do whatever you like with the lists of strings.
Assuming your data does not have any degenerate cases, we will always expect a '}','{' to separate your groups.
Therefore a simple way to get your desired output would be to join the strings together, split on } and then format the resulting list elements.
l = ['{','k0c','k1b','k2b','k3b','}','{','\\g0','\\g1','\\g2','\\g3','}']
out = [x.replace("{,", "{").strip(", ") + " }" for x in ", ".join(l).split("}") if x]
print(out)
['{ k0c, k1b, k2b, k3b }', '{ \\g0, \\g1, \\g2, \\g3 }']
I have a data like this, and I want to add String with comma separated and sum int values.
data=[{"string": "x","int": 1},
{"string": "y","int": 2},
{"string": "z","int": 3}]
I'am expecting an output some thing like this.
Output:
{ "string":"x,y,z","int":"6"}
I tried using reduce function
func = lambda x, y: dict((m, n + y[m]) for m, n in x.items() )
print reduce(func, data)
and i am getting something like this.
{"string": "xyz", "int": "6"}
How to get string with comma separated.
func = lambda x, y: dict((m, n + y[m]) for m, n in x.items() )
You need a custom function to replace n+y[m] (let's say custom_add(a,b)), which,
if arguments are integers to return algebraic sum of them
if arguments are strings, to join them with ',' and return final string
let's implement it.
def custom_join(a,b):
arr = list((a,b))
return sum(arr) if is_int_array(arr) else ','.join(arr)
we have no is_int_array/1 yet. let's do it now.
def is_int_array(arr):
return all(i for i in map(is_int, arr))
no is_int/1. let's do it
def is_int(e):
return isinstance(e, int)
do the same things for strings
def is_str(e):
return isinstance(e, str)
def is_str_array(arr):
return all(i for i in map(is_str, arr))
Summing all of them - https://repl.it/LPRR
OK, this is insane but when you try to implement functional-only approach, you need to be ready such situations -)))
You can use str.join() and sum() with some generator expressions like this:
res = {"string": ','.join(d['string'] for d in data), "int": sum(d['int'] for d in data)}
Output:
>>> res
{'int': 6, 'string': 'x,y,z'}
Question about appropriate data structure:
I have five variables that will have different values
string based on whether they are in US/Alaska and
at half/full resolution.
So I'm building a 5/2/2 (array or list or dict).
I want to access it with x = DStr(var,'AK','H') , e.g..
For Alaska/half-res, what values for OSP/UL/LR/etc, the variables?
This is a static table, values won't change.
There is no obvious ordering to demand 0,1,2 for indices
Problem is, array doesn't like the string indices and
dict wants one key only, not three.
Any ideas?
You can use tuples to index a dict:
>>> values = {
... ("AK", "H"): ("some", "sample", "data", "to", "return"),
... ("AK", "F"): ("more", "sample", "data", "for", "you"),
... # More data here
... }
>>> a, b, c, d, e = values[("AK", "H")]
>>> a
"some"
Or you can use a nest of dicts:
>>> values = {
... "AK": {
... "H": ("some", "sample", "data", "to", "return"),
... "F": ("more", "sample", "data", "for", "you")
... },
... # Other nested dicts here
... }
>>> a, b, c, d, e = values["AK"]["H"]
>>> a
"some"
If you have a class structure for defining the 5 data points as a part of a single object (which would be a good idea to keep the data grouped together if it is related), you can store instances of the class instead of the tuples:
>>> values = {
... ("AK", "H"): MyClass("some", "sample", "data", "to", "return"),
... ("AK", "F"): MyClass("more", "sample", "data", "for", "you"),
... # More data here
... }
>>> obj = values[("AK", "H")]
>>> obj.osp
"some"
or
>>> values = {
... "AK": {
... "H": MyClass("some", "sample", "data", "to", "return"),
... "F": MyClass("more", "sample", "data", "for", "you")
... },
... # Other nested dicts here
... }
>>> obj = values["AK"]["H"]
>>> obj.osp
"some"
Bear in mind that your question is rather unclear. I really don't understand the meaning of the data you want to model, and I don't know how it will be used.
That being said, a class is a good way to define your own data structures. In this case I guess you have OSP, UL, LR, and "etc". So I would define a class for that:
class MyData:
def __init__(self, osp, ul, lr, etc):
self.osp = osp
self.ul = ul
self.lr = lr
self.etc = etc
Then make your lookup table containing instances of the class:
table = {
'AK': {'H': MyData(1,5,20,'something'),
'F': MyData(3,2,28,'spam') },
'FL': {'H': MyData(42,5,20,'eggs'),
'F': MyData(2,13,7,'ham') },
}
Then I can define a function matching the signature you showed in your question. I ignore the argument var because your question doesn't tell me anything about it.
def DStr(var, state, resolution):
return table[state][resolution]
If you have fixed length two strings that will make up a lookup, you can concatenate them together. Might be simpler than having a dict of dict of values. Values can be in a list.
table = {'AKH': [1,"two",3.14],
'AKF': [2,"four", 6.28]
}
state = 'AK'
res = 'F'
table[state+res]
output
[2, 'four', 6.28]
I have a dictionary in Python where the keys are pathnames. For example:
dict["/A"] = 0
dict["/A/B"] = 1
dict["/A/C"] = 1
dict["/X"] = 10
dict["/X/Y"] = 11
I was wondering, what's a good way to print all "subpaths" given any key.
For example, given a function called "print_dict_path" that does this, something like
print_dict_path("/A")
or
print_dict_path("/A/B")
would print out something like:
"B" = 1
"C" = 1
The only method I can think of is something like using regex and going through the entire dictionary, but I'm not sure if that's the best method (nor am I that well versed in regex).
Thanks for any help.
One possibility without using regex is to just use startswith
top_path = '/A/B'
for p in d.iterkeys():
if p.startswith(top_path):
print d[p]
You can use str.find:
def print_dict_path(prefix, d):
for k in d:
if k.find(prefix) == 0:
print "\"{0}\" = {1}".format(k,d[k])
Well, you'll definitely have to loop through the entire dict.
def filter_dict_path( d, sub ):
for key, val in d.iteritems():
if key.startswith(sub): ## or do you want `sub in key` ?
yield key, val
print dict(filter_dict_path( old_dict, sub ))
You could speed this up by using the appropriate data structure: a Tree.
Is your dictionary structure fixed? It would be nicer to do this using nested dictionaries:
{
"A": {
"value": 0
"dirs": {
"B": {
"value": 1
}
"C": {
"value": 1
}
}
"X": {
"value": 10
"dirs": {
"Y": {
"value": 11
}
}
The underlying data structure here is a tree, but Python doesn't have that built in.
This removes one level of indenting, which may make the code in the body of the for loop more readable in some cases
top_path = '/A/B'
for p in (p for p in d.iterkeys() if p.startswith(top_path)):
print d[p]
If you find performance to be a problem, consider using a trie instead of the dictionary