9

I have the following object and lodash "queries" in Node.js (I'm simply running node in the terminal):

var obj = { a: [{ b: [{ c: "apple" }, { d: "not apple" }, { c: "pineapple" }] }] }; > _.get(obj, "a[0].b[0].c") 'apple' > _.get(obj, "a[0].b[1].c") undefined > _.get(obj, "a[0].b[2].c") 'pineapple' 

My question is: is there a way to return an array of values where the path was found to be valid?

Example:

> _.get(obj, "a[].b[].c") ['apple', 'pineapple'] 
5
  • Do you want to get result array for the specific path, something a[0].b? Or any path, as you provided in the question? Commented Aug 29, 2017 at 15:05
  • 4
    Look at jsonpath. github.com/dchester/jsonpath Commented Aug 29, 2017 at 15:09
  • 2
    Thanks to @Tomalak's advice. This task would be pretty easy using jsonpath: jsonpath.query(obj, '$.a[*].b[*].c'); Commented Aug 29, 2017 at 15:13
  • Thanks to @Tomalak and shaochuancs I've got what I wanted. I would appreciate it if one of you would submit it as the answer. Commented Aug 29, 2017 at 19:03
  • Write the answer yourself - you already have working code so all you need to do is copy it, write a short paragraph about it and you're done. I'll upvote, everybody wins. :) Commented Aug 29, 2017 at 21:08

4 Answers 4

6

As @Tomalak has suggested in a comment, the solution was to use JSONPath instead of Lodash.

Their github page: https://github.com/dchester/jsonpath

Example:

> var jp = require("jsonpath") > var obj = { a: [{ b: [{ c: "apple" }, { d: "not apple" }, { c: "pineapple" }] }] }; > jp.query(obj, "$.a[*].b[*].c") [ 'apple', 'pineapple' ] 
Sign up to request clarification or add additional context in comments.

Comments

0

i dont know if this will be the most efficient or what you need but can you use _.each or _.map to create an array if some conditions are valid? maybe something like

let first = _.map(object, (item) => { //change logic for maybe if(item.b.c) { return item.b.c } }) //filter out nulls let second = _.without(first, null) 

Comments

0

Following function may help without using any additional libraries.

function getall(input, path = "", accumulator = []) { path = path.split("."); const head = path.shift(); if (input && input[head] !== undefined) { if (!path.length) { accumulator.push(input[head]); } else if (Array.isArray(input[head])) { input[head].forEach(el => { getall(el, path.join('.'), accumulator); }); } else { getall(input[head], path.join('.'), accumulator); } } return accumulator; } 

Samples

> getall(obj, 'a.b') [ [ { c: 'apple' }, { d: 'not apple' }, { c: 'pineapple' } ] ] > getall(obj, 'a.b.c') [ 'apple', 'pineapple' ] > getall(obj, 'a.b.d') [ 'not apple' ] > getall(obj, 'a.b.e') [] 

Comments

0

How about using flatMap and map

_(obj.a).flatMap('b').map('c').compact();

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.