Уведомления

Группа в Telegram: @pythonsu

#1 Апрель 7, 2011 12:51:26

esal
От:
Зарегистрирован: 2010-10-20
Сообщения: 42
Репутация: +  0  -
Профиль   Отправить e-mail  

как реализовать "XPath" для данных?

Мне в результате нужно написать функц для отбора данных по текстов запросу, похожему на XPath (которая может работать со списками, вложенными деревьями и еще получать атрибуты объектов внутри них). Помогите советом мне, с чего начинать хотя бы? Любые идеи и предложения ..

исходники следующие:


#!/usr/bin/env python
# -*- coding: utf-8 -*-

def path(data):
"""Эта функция позволяет работать с вложенными деревьями, списками и iterable объектами.

Так же, она позволяет получать атрибуты объектов и выбирать данные внутри них.
Все вычисления "ленивые".

>>> class Meta(object):
... def __init__(self, value):
... self.value = value
... self.dvalue = dict(a = value)
... def __repr__(self):
... return u'<meta: %s>' % self.value
>>>
>>> data = {
... 'voices': 100500,
... 'items': [
... {
... 'id': 1,
... 'name': 'User1',
... 'meta': Meta(123),
... },
... {
... 'id': 2,
... 'name': 'User2',
... 'meta': Meta(456),
... },
... 'text item',
... {
... 'name': 'Without id',
... },
... ]
... }
>>> hasattr(path(data).items, '__iter__')
True
>>> list(path(data).voices)
[100500]
>>> list(path(data).items)
[{'meta': <meta: 123>, 'id': 1, 'name': 'User1'}, {'meta': <meta: 456>, 'id': 2, 'name': 'User2'}, 'text item', {'name': 'Without id'}]
>>> list(path(data).items.id)
[1, 2]
>>> list(path(data).items.meta['value'])
[123, 456]
>>> list(path(data).items.meta['dvalue'].a)
[123, 456]
>>> list(path(data).items[2:].name)
['Without id']
>>> items = path(data).items
>>> list(items.name)
['User1', 'User2', 'Without id']
>>> list(items.id)
[1, 2]
>>> # так же должно работать со списком данных
>>> list(path([data, data]).items.meta['dvalue'].a)
[123, 456, 123, 456]
>>> # и с обычными объектами тоже
>>> list(path(Meta(123))['dvalue'].a)
[123]
>>> # и с генераторами
>>> list(path(Meta(x) for x in xrange(10))['dvalue'].a)
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
"""
pass

if __name__ == '__main__':
import doctest
doctest.testmod()



Офлайн

#2 Апрель 7, 2011 20:39:44

doza_and
От:
Зарегистрирован: 2010-08-15
Сообщения: 4138
Репутация: +  252  -
Профиль   Отправить e-mail  

как реализовать "XPath" для данных?

Мне кажется надо прежде всего начать с четкой спецификации требований. У вас насколько я понял не используются * и прочие кванторы - это так задумано что используется только сравнение? Произвольные питоновские объекты в отличии от XPath не образуют дерева - или вы потребуете что это обязательно будет дерево?
Похожие штуки я делал при отображении состава объекта в GUI. Моя реализация близка к http://www.opentradingsystem.com/TradingPlatform/OTS_Python_Object_Browser_.html
Я бы реализовал как рекурсивный генератор

def ListVal(tree,keyList):
if not hasattr(tree,"keys"):
yield tree
return
for k,el in tree.iteritems():
if k==keyList[0]:
for res in ListVal(el,keyList[1:])
yield res
Случай обобщения на классы и списки приведен в otsObjectBrowser.py и достаточно очевиден.
Перебор ключей - не очень эффективная процедура.
Если вы ограничитесь одним образцом (те k==keyList истинно только для одного элемента списка ключей как еслибы он был просто строкой) то возможна существенная оптимизация.



Офлайн

Board footer

Модераторировать

Powered by DjangoBB

Lo-Fi Version