reverse a string value within a dict in python 3 - python

I'm currently working on a program in python 3 that reads in JSON strings and modifies them. I need to search for a value that contains and certain word and then reverse it. Here is the code I have:
msg = '{"company": "Happy, Inc.", "agent": "007"}'
message = json.loads(msg)
for k , v in message.items():
if not k.startswith("_"):
if 'Happy' in v:
message[k] = v[::-1]
print (json.dumps(message))
This reverses the string containing Happy but also reverses the tuples producing this:
{"agent": "007", "company": ".cnI ,yppaH"}
anyone know a way to just reverse the string without reversing the tuples as well?
**I'm teaching myself python and this is my first program using it

If you want to preserve the order of the keys in the JSON, you can parse it into an OrderedDict instead:
>>> message = json.loads(msg, object_pairs_hook=OrderedDict)
>>> message["company"] = message["company"][::-1]
>>> message
OrderedDict([(u'company', u'.cnI ,yppaH'), (u'agent', u'007')])
>>> json.dumps(message, sort_keys=False)
'{"company": ".cnI ,yppaH", "agent": "007"}'

Related

How could I read a dictionary that contains a function from a text file?

I want to read a dictionary from a text file. This dictionary seems like {'key': [1, ord('#')]}. I read about eval() and literal_eval(), but none of those two will work due to ord().
I also tried json.loads and json.dumps, but no positive results.
Which other way could I use to do it?
So Assuming you read the text file in with open as a string and not with json.loads you could do some simple regex searching for what is between the parenthesis of ord e.g ord('#') -> #
This is a minimal solution that reads everything from the file as a single string then finds all instances of ord and places the integer representation in an output list called ord_. For testing this example myfile.txt was a text file with the following in it
{"key": [1, "ord('#')"],
"key2": [1, "ord('K')"]}
import json
import re
with open(r"myfile.txt") as f:
json_ = "".join([line.rstrip("\n") for line in f])
rgx = re.compile(r"ord\(([^\)]+)\)")
rgd = rgx.findall(json_)
ord_ = [ord(str_.replace(r"'", "")) for str_ in rgd]
json.dump() and json.load() will not work because ord() is not JSON Serializable (meaning that the function cannot be a JSON object.
Yes, eval is really bad practice, I would never recommend it to anyone for any use.
The best way I can think of to solve this is to use conditions and an extra list.
# data.json = {'key': [1, ['ord', '#']]} # first one is function name, second is arg
with open("data.json") as f:
data = json.load(f)
# data['key'][1][0] is "ord"
if data['key'][1][0] == "ord":
res = ord(data['key'][1][1])

how to print after the keyword from python?

i have following string in python
b'{"personId":"65a83de6-b512-4410-81d2-ada57f18112a","persistedFaceIds":["792b31df-403f-4378-911b-8c06c06be8fa"],"name":"waqas"}'
I want to print the all alphabet next to keyword "name" such that my output should be
waqas
Note the waqas can be changed to any number so i want print any name next to keyword name using string operation or regex?
First you need to decode the string since it is binary b. Then use literal eval to make the dictionary, then you can access by key
>>> s = b'{"personId":"65a83de6-b512-4410-81d2-ada57f18112a","persistedFaceIds":["792b31df-403f-4378-911b-8c06c06be8fa"],"name":"waqas"}'
>>> import ast
>>> ast.literal_eval(s.decode())['name']
'waqas'
It is likely you should be reading your data into your program in a different manner than you are doing now.
If I assume your data is inside a JSON file, try something like the following, using the built-in json module:
import json
with open(filename) as fp:
data = json.load(fp)
print(data['name'])
if you want a more algorithmic way to extract the value of name:
s = b'{"personId":"65a83de6-b512-4410-81d2-ada57f18112a",\
"persistedFaceIds":["792b31df-403f-4378-911b-8c06c06be8fa"],\
"name":"waqas"}'
s = s.decode("utf-8")
key = '"name":"'
start = s.find(key) + len(key)
stop = s.find('"', start + 1)
extracted_string = s[start : stop]
print(extracted_string)
output
waqas
You can convert the string into a dictionary with json.loads()
import json
mystring = b'{"personId":"65a83de6-b512-4410-81d2-ada57f18112a","persistedFaceIds":["792b31df-403f-4378-911b-8c06c06be8fa"],"name":"waqas"}'
mydict = json.loads(mystring)
print(mydict["name"])
# output 'waqas'
First you need to convert the string into a proper JSON Format by removing b from the string using substring in python suppose you have a variable x :
import json
x = x[1:];
dict = json.loads(x) //convert JSON string into dictionary
print(dict["name"])

JSON from streamed data in Python

I am simply trying to keep the following input and resulting JSON string in order.
Here is the input string and code:
import json
testlist=[]
# we create a list as a tuple so the dictionary order stays correct
testlist=[({"header":{"stream":2,"function":3,"reply":True},"body": [({"format": "A", "value":"This is some text"})]})]
print 'py data string: '
print testlist
data_string = json.dumps(testlist)
print 'json string: '
print data_string
Here is the output string:
json string:
[{"body": [{"format": "A", "value": "This is some text"}], "header": {"stream": 2, "function": 3, "reply": true}}]
I am trying to keep the order of the output the same as the input.
Any help would be great. I can't seem to figure this one point.
As Laurent wrote your question is not very clear, but I give it a try:
OrderedDict.update adds in the above case the entries of databody to the dictionary.
What you seem to want to do is something like data['body'] = databody where databody is this list
[{"format":"A","value":"This is a text\nthat I am sending\n to a file"},{"format":"U6","value":5},{"format":"Boolean","value":true}, "format":"F4", "value":8.10}]
So build first this list end then add it to your dictionary plus what you wrote in your post is that the final variable to be parse into json is a list so do data_string = json.dumps([data])

Extracting data from a nested json structure in python

My json file looks like this:
{"07/01/2015-08/01/2015":
{"ABC": [
["12015618727", "2015-07-29 02:32:01"],
["12024079732", "2015-07-24 13:04:01"],
["12024700142", "2015-07-02 00:00:00"]
]
}
}
I want to extract the numbers 12015618727, 12024079732, 12024700142 from here in python.
I wrote this code:
import json
numbers=set()
input_file=open('filename', 'r')
json_decode=json.load(input_file)
for item in json_decode["07/01/2015-08/01/2015"]["ABC"]:
for j in item:
numbers.add(j[0])
print " ".join(str(x) for x in numbers)
But this doesn't print the numbers.
Python has a json parsing library, see https://docs.python.org/2/library/json.html for details.
Usage:
import json
text = open("file.txt", "r").read()
obj = json.loads(text)
where obj is a python native dict object with nested arrays and dicts.
Edit:
This is the code you want.
import json
numbers=set()
input_file=open('filename.json', 'r')
json_decode=json.load(input_file)
for item in json_decode["07/01/2015-08/01/2015"]["ABC"]:
numbers.add(item[0])
print " ".join(str(x) for x in numbers)
You iterated through each item (the two strings) and added the first letter of each string, hence 1 and 2. Next time, please provide the output you got.
Also, you should attempt to debug your code first. I added a print at the beginning of each loop, and that made the problem pretty clear.

Creating multi-level dictionary from string [Python]

I'm creating a mail "bot" for one of my web services that will periodically collect a queue of e-mail messages to be sent from a PHP script and send them via Google's SMTP servers. The PHP script returns the messages in this format:
test#example.com:Full Name:shortname\ntest2#example.com:Another Full Name:anothershortname\ntest#example.com:Foo:bar
I need to "convert" that into something like this:
{
"test#example.com": [
[
"Full Name",
"shortname"
],
[
"Foo",
"bar"
]
],
"test2#example.com": [
[
"Another Full Name",
"anothershortname"
]
]
}
Notice I need to have only one key per e-mail, even if there are multiple instances of an address. I know I can probably do it with two consecutive loops, one to build the first level of the dictionary and the second to populate it, but there should be a way to do it in one shot. This is my code so far:
raw = "test#example.com:Full Name:shortname\ntest2#example.com:Another Full Name:anothershortname\ntest#example.com:Foo:bar"
print raw
newlines = raw.split("\n")
print newlines
merged = {}
for message in newlines:
message = message.split(":")
merged[message[0]].append([message[1], message[2]])
print merged
I'm getting a KeyError on the last line of the loop, which I take to mean the key has to exist before appending anything to it (appending to a nonexistent key will not create that key).
I'm new to Python and not really familiar with lists and dictionaries yet, so your help is much appreciated!
May work as:
for message in newlines:
message = message.split(":")
temp = []
temp.append(message[1])
temp.append(message[2])
merged[message[0]] = temp
Actually maybe:
for message in newlines:
message = message.split(":")
temp = []
temp.append(message[1])
temp.append(message[2])
if message[0] not in merged:
merged[message[0]] = []
merged[message[0]].append(temp)
I see that you've already accepted an answer, but maybe you're anyhow interested that what you're doing can be easily achieved with defaultdict:
from collections import defaultdict
raw = "test#example.com:Full Name:shortname\ntest2#example.com:Another Full Name:anothershortname\ntest#example.com:Foo:bar"
merged = defaultdict(list)
for line in raw.split('\n'):
line = line.split(':')
merged[line[0]].append(line[1:])
You are right about the error. So you have to check if the key is present. 'key' in dict returns True if 'key' is found in dict, otherwise False. Implementing this, here's your full code (with the debugging print statements removed):
raw = "test#example.com:Full Name:shortname\ntest2#example.com:Another Full Name:anothershortname\ntest#example.com:Foo:bar"
newlines = raw.split("\n")
merged = {}
for message in newlines:
message = message.split(":")
if message[0] in merged:
merged[message[0]].append([message[1], message[2]])
else:
merged[message[0]]=[[message[1], message[2]]]
print merged
Notice the extra brackets for the nested list on the second last line.
Just check for presence of key, if it is not present, create the key,
if it is present, then append the data to existing list.
if(messsage[0] in merged):
merged[message[0]] = [message[1],[message[2]]
else:
merged[message[0]].append([[message[1], message[2]])

Categories

Resources