I am attempting to query some options created in a Wordpress site that utilized an Advanced Custom Fields repeater and create a python list out of them.
I have the query just fine, but it returns typical ACF "option" repeater data in that, it's not stored as a serialized array but rather each field is a separate record that looks like this:
option_name option_value
options_updates_notifier_contact_list_0_un_c_email [email protected]
options_updates_notifier_contact_list_0_un_c_name Kevin
options_updates_notifier_contact_list_1_un_c_email kpirnie [email protected]
options_updates_notifier_contact_list_1_un_c_name Kevin 2
options_updates_notifier_contact_list_2_un_c_email kpirnie [email protected]
options_updates_notifier_contact_list_2_un_c_name Kevin 3
My Code loops this, and gathers up the required elements based on some regex
# setup the regular expression to use
_re = r"options_updates_notifier_contact_list_(\d )_un_c_(\w )"
# hold our returnable list _ret = []
# if there are records
if _rs is not None:
# loop them
for _r in _rs:
# hold the field
_field = _r[0]
# hold the value
_value = _r[1]
# hold the RE match
_match = re.search( _re, _field )
# the index
_idx = int( _match.group( 1 ) )
# the name
_the_name = _match.group( 2 )
# insert at the set index
_ret.insert( _idx, [ _idx, _the_name, _value ] )
# this returns a IndexError: list index out of range
#_ret[ int( _match.group( 1 ) ) ].extend( [ _match.group( 2 ), _value ] )
print( _ret )
Which returns me the following list:
[[0, 'name', 'Kevin'], [1, 'name', 'Kevin 2'], [2, 'name', 'Kevin 3'], [2, 'email', 'kpirnie [email protected]'], [1, 'email', 'kpirnie [email protected]'], [0, 'email', '[email protected]']]
My goal is to have the list be returned like this:
[
[[0, 'name', 'Kevin'], [0, 'email', '[email protected]']],
[[1, 'name', 'Kevin 2'], [1, 'email', 'kpirnie [email protected]']],
[[2, 'name', 'Kevin 3'], [2, 'email', 'kpirnie [email protected]']]
]
Where each name|email combo is it's own list item. How can I do this?
CodePudding user response:
If you start from your current result, you can sort, pair and validate your data like so:
data = [
[0, 'name', 'Kevin'],
[1, 'name', 'Kevin 2'],
[2, 'name', 'Kevin 3'],
[2, 'email', 'kpirnie [email protected]'],
[1, 'email', 'kpirnie [email protected]'],
[0, 'email', '[email protected]']
]
# Sorting
data = sorted(data, key=lambda item: item[0])
# Pairing
it = iter(data)
data = [list(item) for item in zip(it, it)]
# Validation
assert(all(el[0] == item[0][0] for item in data for el in item))
This is assuming that you will have 2 records per index value. If this condition is not fulfilled, the validation won't pass and will raise an exception.
CodePudding user response:
If the number of records with a similar index is unknown or likely to differ, you can store the data in a temporary dictionary and then extract the values:
from collections import defaultdict
# setup the regular expression to use
_re = r"options_updates_notifier_contact_list_(\d )_un_c_(\w )"
# hold our returnable list
_ret = []
_tmp_dict = defaultdict(list)
# if there are records
if _rs is not None:
# loop them
for _r in _rs:
# hold the field
_field = _r[0]
# hold the value
_value = _r[1]
# hold the RE match
_match = re.search(_re, _field)
# the index
_idx = int(_match.group(1))
# the name
_the_name = _match.group(2)
_tmp_dict[_idx].append([_idx, _the_name, _value])
_ret = list(_tmp_dict.values())
You may prefer this because it should be more robust, the only downside is that you need the memory to hold the temporary dict.