Reposting as a corrected version of this question. I have reviewed this, but it didn't help me deal with unknown array nestings.
EDIT: Added information on why Lodash _.get won't work. Here's a Stackblitz. There's an npm library, Object-Scan that would work -- but, I can't get Angular to play nice with that package.
This is for a column renderer component in an Angular app. The user selects a column to display, and the column is mapped to whatever it is. So, in the below example, if user selects to display "Categories", and it is mapped to "interests[categories]", the function then needs to go find values that correspond to that mapping in the data.
Sample data:
const response = {
  id: "1234",
  version: "0.1",
  drinks: ["Scotch"],
  interests: [
    {
      categories: ["baseball", "football"],
      refreshments: {
        drinks: ["beer", "soft drink"]
      }
    },
    {
      categories: ["movies", "books"],
      refreshments: {
        drinks: ["coffee", "tea", "soft drink"]
      }
    }
  ],
  goals: [
    {
      maxCalories: {
        drinks: "350",
        pizza: "700"
      }
    }
  ]
};
For this data, the possible mappings are:
id,
version,
drinks,
interests[categories],
interests[refreshments][drinks],
goals[maxCalories][drinks],
goals[maxCalories][pizza],
Requirement:
I need a recursive function that will work in Angular, and accept two args: one for the data object response, and a second string of the selector mapping that will return the applicable, potentially nested values, iterating through any objects and/or arrays that are encountered. The mapping string may have either dotted or bracketed notation. Readable, self-documenting code is highly desired.
For example, based on the above data object:
- getValues("id", response);should return- ["1234"]
- getValues("version", response);should return- ["0.1"]
- getValues("drinks", response);should return- ["Scotch"]
- getValues("interests.categories", response)should return- ["baseball", "football", "movies", "books"]
- getValues("interests[refreshments][drinks]", response);should return- ["beer", "soft drink", "coffee", "tea", "soft drink" ], accounting for however many items may be in the- interestsarray.
- getValues("goals.maxCalories.drinks", response);should return- ["350"]
Returned values will ultimately be deduped and sorted.
Original function:
function getValues(mapping, row) {
  let rtnValue = mapping
    .replace(/\]/g, "")
    .split("[")
    .map(item => item.split("."))  
    .reduce((arr, next) => [...arr, ...next], [])
    .reduce((obj, key) => obj && obj[key], row)
    .sort();
  rtnValue = [...new Set(rtnValue)]; //dedupe the return values
  return rtnValue.join(", ");
}
The above works fine, just like Lodash' get: if you pass, for example: "interests[0][refreshments][drinks], it works perfectly. But, the mapping is not aware of nested arrays and passes in simply "interests[refreshments][drinks]", which results in undefined. Any subsequent array items have to be accounted for.
 
     
     
    