Как превратить линейную строку в три? - PullRequest
0 голосов
/ 01 ноября 2019

Я использую и создаю набор данных китайских иероглифов с открытым исходным кодом hanzi . В рамках этого набора данных есть строки, которые обеспечивают разложение китайских иероглифов на отдельные единицы (называемые радикалами). Я хочу превратить строки, описывающие декомпозицию символов, в попытки (чтобы я мог использовать networkx для визуализации декомпозиции).

Например, для этой записи базы данных:

{"character":"⺳","definition":"net, network","pinyin":[],"decomposition":"⿱冖八","radical":"⺳","matches":[[0],[0],[1],[1]]}

Разложение для этого персонажа будет таким.

- Node(1, char='⿱')
  - Node(2, char='冖') # an edge connects '⿱' to '冖'
  - Node(3, char='八') # an edge connects '⿱' to '八' 

До сих пор я придумал скрипт, который превращает декомпозиции строк в словари (но не в графы).

decomposition_types = {
    'top-bottom': '⿱',
    'left-right': '⿰',
    'diagonal-corners': '⿻',
    'over-under': '⿺',
    'under-over': '⿹',
    'over-under-reversed': '⿸',
    'top-bottom-middle': '⿳',
    'left-right-middle': '⿲',
    'inside-outside': '⿴',
    'outside-inside': '⿵',
    'outside-inside2': '⿷',
    'inside-outside2': '⿶'
    # 'unknown': '?'
}

decomposition_types_reversed = dict(((value, key) for key, value in decomposition_types.items()))

file = []

if not os.path.isfile('data/dictionary.json'):

    with open('data/dictionary.txt') as d:
        for line in d:
            file.append(json.loads(line))

    for i, item in enumerate(file):
        item['id'] = i + 1

    json.dump(file, open('data/dictionary.json', 'w+'))

else:
    file = json.load(open('data/dictionary.json'))


def is_parsed(blocks):
    for block in blocks:
        if not block['is_unit']:
            return False
    return True


def search(character, dictionary=file):
    for hanzi in dictionary:
        if hanzi['character'] == character:
            return hanzi
    return False


def parse(decomp):
    if len(decomp) == 1:
        return {"spacing": '?'}
    blocks = []
    n_loops = 0
    for item in decomp:
        blocks.append({"char": item, "is_spacing": item in decomposition_types_reversed, "is_unit": False})
    while not is_parsed(blocks):
        for i, item in enumerate(blocks):
            if "is_spacing" in item:
                if item['is_spacing']:
                    next_items = decomposition_types_reversed[item['char']].count('-') + 1
                    can_match = True
                    for x in blocks[i + 1:i + 1 + next_items]:
                        try:
                            if x['char'] in decomposition_types_reversed:
                                can_match = False
                        except KeyError:
                            pass
                    if can_match:
                        blocks[i] = {"spacing": item['char'],
                                     "chars": [l['char'] if 'char' in l else l for l in
                                               blocks[i + 1:i + 1 + next_items]],
                                     "is_unit": True}
                        del blocks[i + 1:i + 1 + next_items]
        n_loops += 1
        if n_loops > 10:
            print(decomp)
            sys.exit()
    return blocks

...