Python Методы рефакторинга для фильтрации словарей - PullRequest
0 голосов
/ 22 марта 2020

У меня есть список словарей, где словари имеют следующую структуру:

{
    "subject" : "subjectValue",
    "object" : "objectValue",
    "prediction" : "predictionValue"
}

В настоящее время у меня есть три метода для фильтрации всех словарей из списка для каждого из полей, как это:

def getSubjects(value, objectValue, predictionValue):
    return [stmt["subject"] for stmt in value if stmt["object"] == objectValue and stmt["prediction"] == predicitonValue]

def getObjects(value, subjectValue, predictionValue):
    return [stmt["object"] for stmt in value if stmt["subject"] == subjectValue and stmt["prediction"] == predicitonValue]

def getPredictions(value, objectValue, subjectValue):
    return [stmt["prediction"] for stmt in value if stmt["object"] == objectValue and stmt["subject"] == subjectValue]

У меня также есть три следующих способа, чтобы просто вывести один из словарей из списка:

def getSubject(value, objectValue, predictionValue):
    return next(stmt["subject"] for stmt in value if if stmt["object"] == objectValue and stmt["prediction"] == predicitonValue)

def getObject(value, subjectValue, predictionValue):
    return next(stmt["object"] for stmt in value if stmt["subject"] == subjectValue and stmt["prediction"] == predicitonValue)

def getPrediction(value, objectValue, subjectValue):
    return next(stmt["prediction"] for stmt in value if stmt["object"] == objectValue and stmt["subject"] == subjectValue)

Есть ли лучший способ добиться этого? Может быть, одним единственным методом или более питонским c способом?

Ответы [ 3 ]

0 голосов
/ 22 марта 2020

Я бы рекомендовал использовать базу данных SQLite3 или Pandas фрейм данных. Учебник по SQLite3

import sqlite3

conn = sqlite3.connect("database.db")
c = conn.cursor()

c.execute("CREATE TABLE IF NOT EXISTS my_table(subject REAL, object REAL, prediction REAL)")

c.execute("INSERT INTO my_table(subject, object, prediction) VALUES (?, ?, ?)",
          (10, 20, 30))

c.execute("SELECT * FROM my_table")

data = c.fetchall()

for row in data:
    print(row)

c.close()
conn.close()
0 голосов
/ 22 марта 2020

Вы можете избавиться от функций next(), всегда возвращая итератор вместо списка. Затем вы можете либо позвонить next() или list() на возвращаемое значение. В целом, вы можете потребовать, чтобы функция вызывалась с аргументами ключевых слов, представляющих ключи, которые вы хотите сопоставить, с ключом, который вы хотите вернуть. Подпись будет выглядеть так:

def pluckFilter(ds, key, **filters):

И вы можете назвать ее так:

pluckFilter(listOfDicts, 'object', subject = 'subjectValue2', prediction = 'predictionValue' )

Это позволит сделать довольно простую реализацию (хотя вам может потребоваться проверить ввод):

listOfDicts = [{
    "subject" : "subjectValue",
    "object" : "objectValue",
    "prediction" : "predictionValue"
    },
    {
    "subject" : "subjectValue2",
    "object" : "objectValue",
    "prediction" : "predictionValue"
    }
]

def pluckFilter(ds, key, **filters):
    filtered = filter(lambda d: all(d[filt] == filters[filt] for filt in filters), ds)
    return map(lambda d: d[key], filtered)

list(pluckFilter(listOfDicts, 'subject', object = 'objectValue', prediction = 'predictionValue' ))
# ['subjectValue', 'subjectValue2']

next(pluckFilter(listOfDicts, 'subject', object = 'objectValue', prediction = 'predictionValue' ))
# 'subjectValue'

list(pluckFilter(listOfDicts, 'object', subject = 'subjectValue2', prediction = 'predictionValue' ))
# ['objectValue']
0 голосов
/ 22 марта 2020

Почему вы не будете использовать pandas?

Вы можете преобразовать список словарей в pandas DataFrame. А затем используйте удобную фильтрацию, чтобы получить те же значения, что и у ваших функций:

df = pd.DataFrame(list_of_dict, index=range(len(list_of_dict)))

например, аналог getSubject:

subjects = subjects = df.loc[(df["object"] == 'objectValue')  & (df["prediction"] == 'predictionValue'), 'subject']
...