1

この質問が重複しているように聞こえることは知っていますが、そうではありません。少なくともしばらくの間、特定の問題について何も解決できませんでした。

次の文字列があります。

"{first : {name : 'test', value : 100}, second : {name : 'test2', value : 50}}"

そして、その文字列を次のような辞書に変換したい:

{'first': {'name': 'test', 'value' : 100}, 'second': {'name': 'test2', 'value' : 50}}

何か案は?私はPython 2.5で作業しています

ありがとう

4

2 に答える 2

6

まず、これらの文字列を辞書から生成する場合 (Python やその他のほとんどすべての言語)、簡単に解析できる方法で文字列を生成することを検討してください。たとえば、Python の場合。repr(d)orjson.dumps(d)は、既存の文字列に非常に似たものを提供しますが、適切な引用符が付いています。


しかし、他の誰かがあなたに与えた混乱した文字列を取得した場合、最も簡単な方法は、それを実際の JSON 文字列に正規表現して解析できるようにすることです。

json.loads(re.sub(r",\s*(\w+)", r", '\1'", 
                  re.sub(r"\s*\{\s*(\w+)", r"{'\1'", x)).replace("'", '"'))

2.5 には組み込みjsonモジュールがないため、おそらくそうしたいと思いpip install simplejsonますが、これを行うことができます。

try:
  import json
except ImportError:
  import simplejson as json

(または、もちろん、必要simplejsonに応じて無条件に要求することもできます。)


別の代替手段は、ast.literal_eval代わりに を使用することですjson.loads。どちらが適切かは、文字列に関する詳細情報によって異なります。JSON は Python 構文よりも制限されているため、入力のソースが心配な場合は安全ですが、入力に JSON が処理できないものが含まれている可能性がある場合は柔軟ではありません1+3j

ただし、 likejsonast2.6 の新機能であり、PyPI で利用できるドロップインの代替品はありません。幸いなことに、2.5にモジュールがあり、2.6 から_astソースをコピーして貼り付けることができますが、これは少し面倒です。http://code.activestate.com/recipes/364469/などのActiveStateにもレシピがあります。literal_evalast.pyliteral_eval

例の文字列には右中括弧も含まれていないため、これでもうまくいきません。タイプミスであることを願っていますが、その場合は問題ありません。

そうでない場合は、そのような場合に実際に何をしたいかを説明する必要があります。閉じていない中括弧を自動的に閉じますか?もしそうなら、閉じていない括弧も問題になる可能性がありますか?

于 2012-11-08T21:06:14.087 に答える
1

Python 2.5 と下位互換性のあるpyparsingを試すことができます。以下の注釈付きコードのコメントを参照してください。

from pyparsing import Suppress, Forward, Word, nums, quotedString, removeQuotes, alphas, alphanums, Group, delimitedList

# define some punctuation expressions
LBRACE,RBRACE,COLON = map(Suppress,"{}:")

# forward declare dict_, because we will use it as part of defining
# dict_value, which we will then use to define dict_ (i.e., the grammar
# is recursive)
dict_ = Forward()

# what does a key value look like (guessing it is any word that
# starts with an alpha or '_', followed by zero or more alphas, nums, or '_'s)
dict_key = Word(alphas+'_',alphanums+'_')

# define possible values for dict entries (expand as needed)
# parse actions do data conversion during parsing, so that we get native Python types,
# not just strings for everything that we have to convert later
integer = Word(nums).setParseAction(lambda t:int(t[0]))
quotedString.setParseAction(removeQuotes)
dict_value = quotedString | integer | dict_

# a dict element is key : value
dict_element = Group(dict_key + COLON + dict_value)

# use a parse action to convert parsed data to dicts while parsing
make_dict = lambda t: dict(t.asList())

# finally, define dict_ using '<<' operator to "inject" the pattern into the previously
# defined Forward - delimitedList(expr) is a short-cut for expr + ZeroOrMore(',' + expr)
dict_ << (LBRACE + (delimitedList(dict_element).setParseAction(make_dict) + RBRACE))

# parse the input string - we get back a real dict, not just a hierarchical list of strings
data = "{first : {name : 'test', value : 100}, second : {name : 'test2', value : 50}}"
dd = dict_.parseString(data)[0]
print type(dd)
print dd
print dd.keys()
print dd['first'].keys()

プリント:

<type 'dict'>
{'second': {'name': 'test2', 'value': 50}, 'first': {'name': 'test', 'value': 100}}
['second', 'first']
['name', 'value']
于 2012-11-09T00:59:04.450 に答える