skip to Main Content

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  [email protected]
options_updates_notifier_contact_list_1_un_c_name   Kevin 2
options_updates_notifier_contact_list_2_un_c_email  [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', '[email protected]'], [1, 'email', '[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', '[email protected]']],
    [[2, 'name', 'Kevin 3'], [2, 'email', '[email protected]']]
]

Where each name|email combo is it’s own list item. How can I do this?

2

Answers


  1. 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', '[email protected]'], 
        [1, 'email', '[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.

    Login or Signup to reply.
  2. 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.

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search