1

I have an array of arrays that looks like this.

const data = [
    ['list1'],
    ['item1', '1'],
    ['item2', '2'],
    ['item3', '3'],
    ['item4', '4'],
    [' ']
    ['list2'],
    ['item1', '1'],
    ['item2', '2'],
    ['item3', '3'],
    ['item4', '4'],
    [' ']
    ['list3'],
    ['item1', '1'],
    ['item2', '2'],
    ['item3', '3'],
    ['item4', '4'],
    [' ']
]

I need to get all of the items between the list1, list2 & list3 and the empty value to build a more structured container so that list1, list2 & list3 include the items as children. e.g. {

const data2 = {
    'list1': {'item1': '1', 'item2': '2', 'item3': '3', 'item4': '4'},
    'list2': {'item1': '1', 'item2': '2', 'item3': '3', 'item4': '4'},
    'list3': {'item1': '1', 'item2': '2', 'item3': '3', 'item4': '4'},
    'list4': {'item1': '1', 'item2': '2', 'item3': '3', 'item4': '4'}
}

Whats the most efficient way to query the data array to get the items between the list headers? I see lodash has a _.slice method which takes an index but I can't see a way to use the value of the array as a delimiter.

2 Answers 2

2

Try this:

const data = [
  ['list1'],
  ['item1', '1'],
  ['item2', '2'],
  ['item3', '3'],
  ['item4', '4'],
  [' '],
  ['list2'],
  ['item1', '1'],
  ['item2', '2'],
  ['item3', '3'],
  ['item4', '4'],
  [' '],
  ['list3'],
  ['item1', '1'],
  ['item2', '2'],
  ['item3', '3'],
  ['item4', '4'],
  [' ']
];

var result = {};
var lastList = null;
for (var item of data) {
  if (item.length == 1 && item[0] != ' ') {
    result[item[0]] = lastList = {};
  }

  else if (lastList != null && item.length == 2) {
    lastList[item[0]] = item[1];
  }
}

console.log(result);

Sign up to request clarification or add additional context in comments.

4 Comments

Should the second if be else if?
Yep this does the trick. Its certainly more understandable than the previous answer. The only issues is that my list names and item names will likely be different. i.e. they won't start with 'list' and 'item'
@user1513388 Does the edited solution work? If not, show us your real data, or describe it.
Change == to be ===
2

You could reduce the whole array by using a closure over a reference to the last object with the given key.

var data = [['list1'], ['item1', '1'], ['item2', '2'], ['item3', '3'], ['item4', '4'], [' '], ['list2'], ['item1', '1'], ['item2', '2'], ['item3', '3'], ['item4', '4'], [' '], ['list3'], ['item1', '1'], ['item2', '2'], ['item3', '3'], ['item4', '4'], [' ']],
    result = data.reduce(function (ref) {
        return function (r, a) {
            if (1 in a) {
                ref[a[0]] = a[1];
            } else if (a[0].trim()) {
                r[a[0]] = {};
                ref = r[a[0]]
            }
            return r;
        };
    }(undefined), {});

console.log(result);
.as-console-wrapper { max-height: 100% !important; top: 0; }

3 Comments

I get a type error TypeError: Cannot use 'in' operator to search for '1' in undefined on the if (1 in a) line if I try this.
@user1513388, it works even in IE11, where do you get the error from?
I'm using nodeJS

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.