3

I am relatively new to Javascript. I am struggling with data wrangling. I would like to avoid loops.

I need to keep the higher levels of structure of "data_1", but insert an object in place of each of the key values of the form {name: "Key n", length: int}

The objects have of the following structures:

const data_1 = {
  Category1: ["Key A", "Key B", "Key C"],
  Category2: ["Key D", "Key E", "Key F"],
  Category3: ["Key G", "Key H"]
}

const data_2 = {
  "Key A": 100,
  "Key B": 200,
  "Key C": 300,
  "Key D": 400,
  "Key E": 400,
  "Key F": 300,
  "Key G": 200,
  "Key H": 100
}

The target structure should be:

result = {
  Category1: [{name:"Key A", length:100}, {name:"Key B", length:200}, {name: "Key C", length:300}],
  Category2: [{name:"Key D", length:400}, {name:"Key E", length:400}, {name: "Key F", length:300}],
  Category3: [{name:"Key G", length:200}, {name:"Key H", length:100}]
}

I suspect the way to tackle this is something akin to the following pseudo code. I am struggling to define an object as [name: key, length:data_2.key] .

let results = Object.fromEntries(data_1.map(key => [name: key, length:data_2.key]));

Any and all help is appreciated :)

4 Answers 4

2

A reduce will do the trick and be quite readable too

const result = Object.entries(data_1).reduce((acc, [key, vals]) => {
  acc[key] = vals.map(val => ({ name: val,length: data_2[val] }));
  return acc;
}, {});
console.log(result);
<script>
const data_1 = {
  Category1: ["Key A", "Key B", "Key C"],
  Category2: ["Key D", "Key E", "Key F"],
  Category3: ["Key G", "Key H"]
}

const data_2 = {
  "Key A": 100,
  "Key B": 200,
  "Key C": 300,
  "Key D": 400,
  "Key E": 400,
  "Key F": 300,
  "Key G": 200,
  "Key H": 100
}</script>

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

Comments

2
  • Using Object#entries, get list of key-value pairs from data_1
  • Using Array#reduce, iterate over the above while updating the resulting object
    • In each iteration, add the new pair where the value is the list of objects having name and length generated using Array#map. We use the spread operator (...acc) to preserve existing accumulated pairs in every iteration.

const 
  data_1 = { Category1: ["Key A", "Key B", "Key C"], Category2: ["Key D", "Key E", "Key F"], Category3: ["Key G", "Key H"] },
  data_2 = { 'Key A': 100, 'Key B': 200, 'Key C': 300, 'Key D': 400, 'Key E': 400, 'Key F': 300, 'Key G': 200, 'Key H': 100 };

const result = Object.entries(data_1).reduce((acc, [key, names]) => ({
  ...acc,
  [key]: names.map(name => ({ name, length: data_2[name] }))
}), {});

console.log(result);

2 Comments

Tricky syntax... OP might need to be told what the ...acc followed by a comma operator actually does. I for one am intrigued by the ...acc
yeah, I wouldn't mind a quick explanation. Tryin' to learn. :)
0

If we grab the entries, we can map over the keys and get each of them like this. Then we can create an object from the transformed entries.

const data_1 = {
  Category1: ["Key A", "Key B", "Key C"],
  Category2: ["Key D", "Key E", "Key F"],
  Category3: ["Key G", "Key H"]
};

const data_2 = {
  "Key A": 100,
  "Key B": 200,
  "Key C": 300,
  "Key D": 400,
  "Key E": 400,
  "Key F": 300,
  "Key G": 200,
  "Key H": 100
};

const data_3 = Object.fromEntries(
    Object.entries(data_1)
        .map(([cat, keys]) => [cat, keys.map((key) => ({ name: key, length: data_2[key] }))]
    )
);

console.log(data_3);

2 Comments

Ok, thanks again caTS :) So the first conceptual bit I was missing was the Object.entries(data_1) to split up that structure. So the idea is we first take the entries from each of the categories ( "cat 1": [key1, ... key n] ) we then map over that specifying that for each of the cats and their respective keys we want an object, which is defined with the following ({ name: key, length: data_2[key] }) . makes sense, thanks.
@Skyehawk Yes that is correct. "cats" is short for categories :p
0

You can do something like this:

const result = {};

Object.keys(data_1).forEach((key) => {
  const item = data_1[key];
  result[key] = item.map((key) => {
    return { name: key, length: data_2[key] };
  });
});

Either way, seems a bit convoluted to use objects in that manner, when you could maybe use arrays for the data format.

Here's a snippet with a working example:

const data_1 = {
  Category1: ['Key A', 'Key B', 'Key C'],
  Category2: ['Key D', 'Key E', 'Key F'],
  Category3: ['Key G', 'Key H'],
};

const data_2 = {
  'Key A': 100,
  'Key B': 200,
  'Key C': 300,
  'Key D': 400,
  'Key E': 400,
  'Key F': 300,
  'Key G': 200,
  'Key H': 100,
};

const result = {};

Object.keys(data_1).forEach((key) => {
  const item = data_1[key];
  result[key] = item.map((key) => {
    return { name: key, length: data_2[key] };
  });
});

console.log(result);

Comments

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.