简体   繁体   中英

Convert list with one item to item itself in dict value

For example, there is a dictionary with key-value pairs, where the values are lists with different "content". Some lists have only one element. These elements can be different types of data.

Question: What is the most efficient way to convert list type key values with one element into the element itself in the dict values?

Input data

{
  "key1": ["text"],
  "key2": ["text", "text"],
  "key3": [{"key0": 0}],
  "key4": [{"key0": 0, "key1": 1}],
  "key5": [],
  "key6": [[]],
  "key7": [["text"]],
  "key8": [[{"key0": 0}]]
}

Expected output data

{
  "key1": "text",
  "key2": ["text", "text"],
  "key3": {"key0": 0},
  "key4": {"key0": 0, "key1": 1},
  "key5": "",
  "key6": "",
  "key7": "text",
  "key8": {"key0": 0}
}

What I have tried

{k: v[0] for k, v in dct.items()}

Output of my code with the issues and comments

{
 'key1': 'text',
 'key2': 'text', <- ISSUE 1 should be ["text", "text"]
 'key3': {'key0': 0},
 'key4': {'key0': 0, 'key1': 1},
 'key5': <- ISSUE 2 Raises ERROR "IndexError: list index out of range" which is quite expected, should be ""
 'key6': [], <- ISSUE 3 should be ""
 'key7': ['text'], <- ISSUE 4 should be "text"
 'key8': [{'key0': 0}] <- ISSUE 5 should be {'key0': 0}
} 

What is the most efficient way to convert dict in Input data to the dict in the Expected output data ?

In order to tackle this problem, I concentrate on how to convert the value: I create a function called delist to delete the list with 1 element:

def delist(value):
    while isinstance(value, list) and len(value) == 1:
        value = value[0]
    if value == []:
        value = ""
    return value

Hopefully, the logic is easy enough to understand. To use it:

data = {
  "key1": ["text"],
  "key2": ["text", "text"],
  "key3": [{"key0": 0}],
  "key4": [{"key0": 0, "key1": 1}],
  "key5": [],
  "key6": [[]],
  "key7": [["text"]],
  "key8": [[{"key0": 0}]]
}

new_data = {k: delist(v) for k, v in data.items()}

And new_data is

{'key1': 'text',
 'key2': ['text', 'text'],
 'key3': {'key0': 0},
 'key4': {'key0': 0, 'key1': 1},
 'key5': '',
 'key6': '',
 'key7': 'text',
 'key8': {'key0': 0}}

here's a one-liner for it using np.ravel()

d = {
  "key1": ["text"],
  "key2": ["text", "text"],
  "key3": [{"key0": 0}],
  "key4": [{"key0": 0, "key1": 1}],
  "key5": [],
  "key6": [[]],
  "key7": [["text"]],
  "key8": [[{"key0": 0}]]
}

out = {k: list(np.ravel(v))  if np.ravel(v).size>1 else (np.ravel(v)[0] if np.ravel(v).size==1 else '')  for k,v in d.items()}


Output:

{'key1': 'text',
 'key2': ['text', 'text'],
 'key3': {'key0': 0},
 'key4': {'key0': 0, 'key1': 1},
 'key5': '',
 'key6': '',
 'key7': 'text',
 'key8': {'key0': 0}}

Perhaps not the most elegant (actually pretty ugly) but working solution to the problem in case I will not receive something smarter.

# input data
dct = {
  "key1": ["text"],
  "key2": ["text", "text"],
  "key3": [{"key0": 0}],
  "key4": [{"key0": 0, "key1": 1}],
  "key5": [],
  "key6": [[]],
  "key7": [["text"]],
  "key8": [[{"key0": 0}]]
}

# define function
def delist(dct):
    new_dct = {}
    for k, v in dct.items():
        if v:
            if len(v) > 1:
                new_dct[k] = v
            else:
                if v[0]:
                    if type(v[0])==list:
                        new_dct[k] = v[0][0]
                    else:
                        new_dct[k] = v[0]
                else:
                    new_dct[k] = ""         
        else:
            new_dct[k] = ""
    return new_dct

# apply function to input data
delist(dct)

Returns

{
 'key1': 'text',
 'key2': ['text', 'text'],
 'key3': {'key0': 0},
 'key4': {'key0': 0, 'key1': 1},
 'key5': '',
 'key6': '',
 'key7': 'text',
 'key8': {'key0': 0}
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM