programing

조건이 충족되는 경우에만 dict에 추가

projobs 2021. 1. 14. 08:00
반응형

조건이 충족되는 경우에만 dict에 추가


urllib.urlencode웹 POST 매개 변수를 빌드하는 데 사용 하고 있지만 다른 값이 None존재 하는 경우에만 추가하고 싶은 몇 가지 값 이 있습니다.

apple = 'green'
orange = 'orange'
params = urllib.urlencode({
    'apple': apple,
    'orange': orange
})

잘 작동하지만 orange변수를 선택 사항으로 만들면 매개 변수에 추가되지 않도록 어떻게 방지 할 수 있습니까? 다음과 같은 것 (의사 코드) :

apple = 'green'
orange = None
params = urllib.urlencode({
    'apple': apple,
    if orange: 'orange': orange
})

나는 이것이 충분히 명확하기를 바랍니다. 누구든지 이것을 해결하는 방법을 알고 있습니까?


이니셜을 만든 후 키를 별도로 추가해야합니다 dict.

params = {'apple': apple}
if orange is not None:
    params['orange'] = orange
params = urllib.urlencode(params)

파이썬에는 키를 조건부로 정의하는 구문이 없습니다. 이미 모든 것을 순서대로 가지고 있다면 사전 이해력을 사용할 수 있습니다.

params = urllib.urlencode({k: v for k, v in (('orange', orange), ('apple', apple)) if v is not None})

그러나 그것은 매우 읽기 어렵습니다.


sqreept의 답변에 편승하려면 dict원하는대로 작동 하는 하위 클래스가 있습니다.

class DictNoNone(dict):
    def __setitem__(self, key, value):
        if key in self or value is not None:
            dict.__setitem__(self, key, value)


d = DictNoNone()
d["foo"] = None
assert "foo" not in d

이렇게하면 기존 키의 값을로 변경할None있지만 None존재하지 않는 키에 할당 하는 것은 작동하지 않습니다. 당신이 항목을 설정 원하는 경우 None제거 가 이미 존재하는 경우 사전에서 그것을, 당신이 할 수 있습니다 :

def __setitem__(self, key, value):
    if value is None:
        if key in self:
            del self[key]
    else:
        dict.__setitem__(self, key, value)

건설 중에 전달하면의 값이 들어갈 None 수 있습니다 . 이를 피 __init__하려면 필터링 하는 방법을 추가하십시오 .

def __init__(self, iterable=(), **kwargs):
    for k, v in iterable:
        if v is not None: self[k] = v
    for k, v in kwargs.iteritems():
        if v is not None: self[k] = v

사전을 생성 할 때 원하는 조건을 전달할 수 있도록 작성하여 일반화 할 수도 있습니다 .

class DictConditional(dict):
    def __init__(self, cond=lambda x: x is not None):
        self.cond = cond
    def __setitem__(self, key, value):
        if key in self or self.cond(value):
            dict.__setitem__(self, key, value)

d = DictConditional(lambda x: x != 0)
d["foo"] = 0   # should not create key
assert "foo" not in d

꽤 오래된 질문이지만 여기에 빈 딕셔너리로 ​​딕셔너리를 업데이트하는 것은 아무것도하지 않는다는 사실을 사용하는 대안이 있습니다.

def urlencode_func(apple, orange=None):
    kwargs = locals().items()
    params = dict()
    for key, value in kwargs:
        params.update({} if value is None else {key: value})
    return urllib.urlencode(params)

params = urllib.urlencode({
    'apple': apple,
    **({'orange': orange} if orange else {}),
})

할당 후 없음을 지울 수 있습니다.

apple = 'green'
orange = None
dictparams = {
    'apple': apple,
    'orange': orange
}
for k in dictparams.keys():
    if not dictparams[k]:
        del dictparams[k]
params = urllib.urlencode(dictparams)

Another valid answer is that you can create you own dict-like container that doesn't store None values.

class MyDict:
    def __init__(self):
        self.container = {}
    def __getitem__(self, key):
        return self.container[key]
    def __setitem__(self, key, value):
        if value != None:
            self.container[key] = value
    def __repr__(self):
        return self.container.__repr__()

a = MyDict()
a['orange'] = 'orange';
a['lemon'] = None

print a

yields:

{'orange': 'orange'}

I did this. Hope this help.

apple = 23
orange = 10
a = {
    'apple' : apple,
    'orange' if orange else None : orange if orange else None
}

Expected output : {'orange': 10, 'apple': 23}

Although, if orange = None , then there will be a single entry for None:None. For example consider this :

apple = 23
orange = None
a = {
    'apple' : apple,
    'orange' if orange else None : orange if orange else None
}

Expected Output : {None: None, 'apple': 23}


fruits = [("apple", get_apple()), ("orange", get_orange()), ...]

params = urllib.urlencode({ fruit: val for fruit, val in fruits if val is not None })

I really like the neat trick in the answer here: https://stackoverflow.com/a/50311983/3124256

But, it has some pitfalls:

  1. Duplicate if tests (repeated for key and value)
  2. Pesky None: None entry in the resulting dict

To avoid this, you can do the following:

apple = 23
orange = None
banana = None
a = {
    'apple' if apple else None: apple,
    'orange' if orange else None : orange,
    'banana' if banana else None: banana,
    None: None,
}
del a[None]

Expected Output : {'apple': 23}

Note: the None: None entry ensures two things:

  1. The None key will always be present (del won't throw an error)
  2. The contents of 'None values' will never exist in the dict (in case you forget to del afterwards)

If you aren't worried about these things, you can leave it out and wrap the del in a try...except (or check if the None key is present before deling). To address number 2 alternatively, you could also put the conditional check on the value (in addition to the key).

ReferenceURL : https://stackoverflow.com/questions/14263872/only-add-to-a-dict-if-a-condition-is-met

반응형