+ (cl-flet*
+ ((rd-assoc (list)
+ ;; given LIST of fields, return a list of data, ignoring empty fields
+ (rd (lambda (elem) (assoc-plus elem csv-record)) list))
+ (mapcar-assoc (list)
+ ;; given LIST of fields,return a list of data with nil in place of an empty field
+ (mapcar (lambda (elem) (cdr (assoc elem csv-record))) list))
+ (assoc-expand (e)
+ ;; E = data-field-name | (field-name-field data-field)
+ ;; get data from the csv-record and return
+ ;; (field-name data) or nil.
+ (let ((data-name (if (consp e) (cdr (assoc (car e) csv-record)) e))
+ (data (assoc-plus (if (consp e) (cadr e) e) csv-record)))
+ (if data (list data-name data))))
+ (replace-num (num string)
+ ;; in STRING, replace all groups of numbers with NUM
+ (replace-regexp-in-string "[0-9]+" (number-to-string num) string))
+ (expand-repeats (list)
+ ;; return new list where elements from LIST in form
+ ;; (repeat elem1 ...) become ((elem1 ...) [(elem2 ...)] ...)
+ ;; For as many repeating numbered fields exist in the csv fields.
+ ;; elem can be a string or a tree (a list with possibly lists inside it)
+ (-reduce-from (lambda (acc arg)
+ (if (not (and (consp arg) (eq (car arg) 'repeat)))
+ (cons arg acc)
+ (setq arg (cdr arg))
+ (let* ((i 1)
+ (first-field (car (flatten arg))))
+ (setq acc (cons arg acc))
+ ;; use first-field to test if there is another repetition.
+ (while (member (replace-num (setq i (1+ i)) first-field) csv-fields)
+ (cl-labels ((fun (cell)
+ (if (consp cell)
+ (mapcar #'fun cell)
+ (replace-num i cell))))
+ (setq acc (cons (fun arg) acc))))
+ acc))) nil list))
+
+ (map-bbdb3 (root-mapping)
+ ;; ROOT-MAPPING = a root element from bbdb3-csv-import-mapping-table.
+ ;;
+ ;; Get the actual csv-fields, including variably repeated ones flattened
+ ;; by one because potentially repeated fields are put in sub-lists so they
+ ;; can be as one thing, but after they are, that extra depth is no longer
+ ;; useful. This makes for a little quirk: address mappings without 'repeat
+ ;; need to be grouped in a list because they contain sublists that we
+ ;; don't want flattened. I've decided that is a better trade off than more
+ ;; complex code.
+ (flatten1 (expand-repeats (cdr (assoc bbdb-arg bbdb3-csv-import-mapping-table)))))
+ (map-assoc (field)
+ ;; For mappings with just 1 simple csv-field, get it's data
+ (assoc-plus (car (map-bbdb3 field)) csv-record)))