Python лямбда-функции, перебирая кортеж и список - PullRequest
0 голосов
/ 10 января 2020

Предположим, у вас есть класс Table, который содержит атрибут: записи (список словарей) и ключи, которые являются первичным ключом каждой таблицы (как и SQL) - кортеж

Мне нужно написать Лямбда-функция, которая берет новую строку и затем выдает True или False, если все значения ключей в новой строке уже находятся в таблице

Например:

# Table: orders

keys = ('product_id', 'customer_id')

records: [{'product_id': 51, 'customer_id' : 10, 'units':9},
          {'product_id': 32, 'customer_id' : 11, 'units':33},
          {'product_id': 39, 'customer_id' : 47, 'units':2}]

и сейчас новая строка, которую мы хотим проверить:

{'product_id': 51, 'customer_id' : 10, 'units': 77 }

Это вернет True, потому что product_id==51 и customer_id==10 точно так же, как первый словарь в записи (единицы измерения не имеют значения, потому что это не ключ).

Однако это:

{'product_id': 51, 'customer_id' : 11, 'units':9}

Вернет False, потому что нет строк с product_id==51 и customer_id==11

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

contains_key = lambda self, new_row: list(filter(  
  (lambda con: con[self.__key]), 
  [record for record in self.__records] 
))

Объяснение: "Я" - это стол, за которым мы работаем В порядке, new_row - строка (словарь) для проверки
self .__ keys - кортеж ключей (как первичные ключи в sql), а self .__ records - список словарей = "" "строк в sql table "" ")
Функция находится внутри класса Table (поэтому она находится в форме" self ")

class Table:
    def __init__(self, key_set):
        self.__key = tuple(key_set)
        self.__records = []

    def add_record(self, new_record):
        self.__records.append(new_record)

Ответы [ 3 ]

2 голосов
/ 10 января 2020

Простое использование any и all поможет: "проверяет, совпадают ли all ключи any записи с новая запись ":

print(any(all(new_record[key] == record[key] for key in keys) for record in records))

Хорошая вещь с этими функциями заключается в коротком замыкании: всякий раз, когда ключ не совпадает - запись будет пропущена, а когда сопоставлена ​​запись - нет будет проверено больше записей.


Я оставлю это вам в качестве упражнения, чтобы превратить это в lambda:)

0 голосов
/ 10 января 2020

Примерно так:

class Table:
    def __init__(self, key):
        # using the __ in an odd way
        self.__key = key
        self.__records = []

    # only using lambda because you must, it's pointless
    contains_key = lambda self, record: any(all(record[f] == r[f] for f in self.__key) for r in self.__records)

    def add(self, record):
        if not self.contains_key(record):
            self.__records.append(record)
        else:
            raise Exception('duplicate key')


t = Table(('product_id', 'customer_id'))
t.add({'product_id': 51, 'customer_id': 10, 'units': 9})
t.add({'product_id': 32, 'customer_id': 11, 'units': 33})
t.add({'product_id': 39, 'customer_id': 47, 'units': 2})
# fails
t.add({'product_id': 39, 'customer_id': 47, 'units': 2})

Но если это то, чему вас учат, я бы искал лучший класс.

Если я заменю:

# fails
t.add({'product_id': 39, 'customer_id': 47, 'units': 2})

С

t.add({'customer_id': '13', 'product_id': '1234-5', 'units': 9})
print(t.contains_key({'customer_id': '13', 'product_id': '1234-5', 'units': 3}))

Результат True.

0 голосов
/ 10 января 2020

Вот канонический ответ для начала:

def has_row(records, keys, row):
    return any(
        all(row[k] == x[k] for k in keys)
        for x in records
    )

Преобразование в «лямбда-функцию» тривиально:

has_row = (lambda records, keys, row:
    any(
        all(row[k] == x[k] for k in keys)
        for x in records
    )
)

Если вы не «разрешено» использовать any или all, их можно заменить следующим образом:

any = (lambda xs:
    bool(next(filter(lambda x: x, xs), False))
)

# Alternatively, without using next:
any = (lambda xs:
    len(list(filter(lambda x: x, xs))) != 0
)

all = (lambda xs:
    len(list(filter(lambda x: not x, xs))) == 0
)
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...