0

So i have this kind of array from json

data : [{
    article_categories : {
        id : "xxx",
        name : "xxx"
    },
    article : "xxx",
    publisher : "xxx"
}]

I wanted to create another multi dimension array for those array and i want to keep the fields name (the name "article","publisher" and so on in the array) with value in there but i have no idea to get fields name

And i also want to do some conditional if to only include some fields into my new array by checking from this array

thead: [
    { key: "article"},
    { key: "article_categories.name"},
    .....
]

so i the end there will be array like this

newArray: [
 {article:"xxx",publisher: "xxx",article_categories.name:"xxx"},
 {article:"xxx",publisher: "xxx",article_categories.name:"xxx"}
 ....
]

how to do that? i tried

thead.forEach(function(column){
  data.forEach(function(key,value){
      if(column.key == key){
         newArray[key] = value
      }
  })
})

but it just not working....

3 Answers 3

1

If you're open to use lodash, it will be so simple. Lodash is efficient in evaluating JSON expressions using .get() method, so you won't be bothered to evaluate the expression against objects.

.chain() adds icing on the cake, making the code simpler to read, yet performing many complex operations under the hood.

Try the following snippet:

var keys = [{
    key: "article"
  },
  {
    key: "article_categories.name"
  }
];

var data = [{
  article_categories: {
    id: "xxx",
    name: "xxx"
  },
  article: "xxx",
  publisher: "xxx"
}];

var result = _.chain(data)
  .map(function(item) {
    var object = {};

    keys.forEach(function(key) {
      object[key.key] = _.get(item, key.key);
    });

    return object;
  })
  .value();

console.log(result);
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.4/lodash.min.js"></script>

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

4 Comments

That requires loading a 70kb (minified!) library just to iterate through an array... :/
well i already using lodash so i don;t mind it, but sorry i have another question but still related to this... what if my thead json array is an object and be like this thead: { article : "string", publisher: "string", ....} how do i modified those code?
@LaurensiusTony -- In that case, you will only be interested in the object's keys. So, you can replace keys.forEach with _.keys(tdata).forEach( ... ).
tdata is what? and also i still don't quite understand your code, it so simple that is seems like a magic...
1

I think that first, you should simplify this :

thead = [
    { key: "article"},
    { key: "article_categories.name"},
    .....
]

as this :

thead = ["article", "article_categories.name"]

Here's my go at it :

const data = [{
		article_categories : {
			id : "xxx",
			name : "xxx"
		},
		article : "xxx",
		publisher : "xxx"
	}],
	thead = ["article", "article_categories.name"]

const newArray = data.map( obj => {
	let output = {}
	thead.forEach(key => {
		if(key.includes(".")){
			let subkeys = key.split(".")
			output[key] = obj[subkeys[0]][subkeys[1]]
		} else {
			output[key] = obj[key]
		}
	})
	return output
})

console.log(newArray)

3 Comments

What if article_categories.name is changed to something like a.b[0].c? Using lodash is a pain in terms of loading a library, but is better suited in this case because parsing JSON expression and evaluating it is something like reinventing the wheel, and is of-course prone to errors.
If it's changed, then the code will need to be adjusted. In the meantime, OP said nothing about changing it, this answers the question and doesn't load a 70k library ;)
Haha, that justifies it for now :)
1

You can use a flatten function to flatten the object with dot notation.

Then map the flattened object to take an item each and filter only the keys that are allowed and reduce to reconstruct the object.

To answer your original question, you can use Object.keys() to get the keys of an Object

let data = [{
    article_categories : {
        id : "xxx",
        name : "xxx"
    },
    article : "xxx",
    publisher : "xxx"
},{
    article_categories : {
        id : "xxx2",
        name : "xxx2"
    },
    article : "xxx2",
    publisher : "xxx2"
}]

let thead = [
    { key: "article"},
    { key: "article_categories.name"},
];

let allowed_keys = thead.map(x=> x.key);

let flattened = data.map(item => flatten(item, '', ''));

// console.log(flattened);

let result = flattened.map(item => {
  return Object.keys(item)
    .filter(key => allowed_keys.includes(key))
    .reduce((obj, key) => {
      obj[key] = item[key];
      return obj;
    }, {})
});

console.log(result);


/**
 * Recursively flattens a JSON object using dot notation.
 *
 * NOTE: input must be an object as described by JSON spec. Arbitrary
 * JS objects (e.g. {a: () => 42}) may result in unexpected output.
 * MOREOVER, it removes keys with empty objects/arrays as value (see
 * examples bellow).
 *
 * @example
 * // returns {a:1, 'b.0.c': 2, 'b.0.d.e': 3, 'b.1': 4}
 * flatten({a: 1, b: [{c: 2, d: {e: 3}}, 4]})
 * // returns {a:1, 'b.0.c': 2, 'b.0.d.e.0': true, 'b.0.d.e.1': false, 'b.0.d.e.2.f': 1}
 * flatten({a: 1, b: [{c: 2, d: {e: [true, false, {f: 1}]}}]})
 * // return {a: 1}
 * flatten({a: 1, b: [], c: {}})
 *
 * @param obj item to be flattened
 * @param {Array.string} [prefix=[]] chain of prefix joined with a dot and prepended to key
 * @param {Object} [current={}] result of flatten during the recursion
 *
 * @see https://docs.mongodb.com/manual/core/document/#dot-notation
 */
function flatten (obj, prefix, current) {
  prefix = prefix || []
  current = current || {}
  if (typeof (obj) === 'object' && obj !== null) {
    Object.keys(obj).forEach(key => {
      flatten(obj[key], prefix.concat(key), current)
    })
  } else {
    current[prefix.join('.')] = obj
  }
  return current
}

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.