leemon
leemon

Reputation: 1061

lodash pick in nested array

I have an array of objects like this:

{
  "sizes":{
     "thumbnail":{
        "height":300,
        "width":300,
        "url":"http://example.com/wp-content/uploads/2017/04/web-300x300.jpg",
        "orientation":"landscape"
     },
     "medium":{
        "height":267,
        "width":400,
        "url":"http://example.com/wp-content/uploads/2017/04/web-400x267.jpg",
        "orientation":"landscape"
     },
     "large":{
        "height":441,
        "width":660,
        "url":"http://example.com/wp-content/uploads/2017/04/web-1024x684.jpg",
        "orientation":"landscape"
     },
     "full":{
        "url":"http://example.com/wp-content/uploads/2017/04/web.jpg",
        "height":1200,
        "width":1796,
        "orientation":"landscape"
     }
  },
  "mime":"image/jpeg",
  "type":"image",
  "subtype":"jpeg",
  "id":3589,
  "url":"http://example.com/wp-content/uploads/2017/04/web.jpg",
  "alt":"",
  "link":"http://example.com/web/",
  "caption":""
}

I'm using the following snippet to create a new array with just the alt, caption, id and url keys in the array:

images.map( ( image ) => pick( image, [ 'alt', 'caption', 'id', 'url' ] ) ),

My question is, how can I pick the sizes.thumbnail.url key instead of the root url key? Is it possible? If so, how?

Thanks in advance

Upvotes: 2

Views: 17322

Answers (3)

Ori Drori
Ori Drori

Reputation: 191976

Create an object with the url property and the value of sizes.thumbnail.url using _.get(), and combine it with to the results of the _.pick().

Note: I've used object spread to merge the results, but you can use Object.assign() or lodash's equivalent instead.

const images = [{"sizes":{"thumbnail":{"height":300,"width":300,"url":"http://example.com/wp-content/uploads/2017/04/web-300x300.jpg","orientation":"landscape"},"medium":{"height":267,"width":400,"url":"http://example.com/wp-content/uploads/2017/04/web-400x267.jpg","orientation":"landscape"},"large":{"height":441,"width":660,"url":"http://example.com/wp-content/uploads/2017/04/web-1024x684.jpg","orientation":"landscape"},"full":{"url":"http://example.com/wp-content/uploads/2017/04/web.jpg","height":1200,"width":1796,"orientation":"landscape"}},"mime":"image/jpeg","type":"image","subtype":"jpeg","id":3589,"url":"http://example.com/wp-content/uploads/2017/04/web.jpg","alt":"","link":"http://example.com/web/","caption":""}];

const result = images.map((image) => ({
  ..._.pick(image, ['alt', 'caption', 'id']),
  url: _.get(image, 'sizes.thumbnail.url')
}));

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

A more generic solution would a function that accepts a list of paths, and generate an array of pairs [last part of path, value]. The function converts the pairs to an object using _.fromPairs() (or Object.fromEntries()):

const deepPick = (paths, obj) => 
  _.fromPairs(paths.map(p => [
    _.last(p.split('.')),
    _.get(obj, p),
  ]))

const images = [{"sizes":{"thumbnail":{"height":300,"width":300,"url":"http://example.com/wp-content/uploads/2017/04/web-300x300.jpg","orientation":"landscape"},"medium":{"height":267,"width":400,"url":"http://example.com/wp-content/uploads/2017/04/web-400x267.jpg","orientation":"landscape"},"large":{"height":441,"width":660,"url":"http://example.com/wp-content/uploads/2017/04/web-1024x684.jpg","orientation":"landscape"},"full":{"url":"http://example.com/wp-content/uploads/2017/04/web.jpg","height":1200,"width":1796,"orientation":"landscape"}},"mime":"image/jpeg","type":"image","subtype":"jpeg","id":3589,"url":"http://example.com/wp-content/uploads/2017/04/web.jpg","alt":"","link":"http://example.com/web/","caption":""}];

const result = images.map(image => deepPick(
  ['alt', 'caption', 'id', 'sizes.thumbnail.url'], 
  image
));

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

Upvotes: 9

Parth Raval
Parth Raval

Reputation: 4423

var array = [{"sizes":{"thumbnail":{"height":300,"width":300,"url":"http://example.com/wp-content/uploads/2017/04/web-300x300.jpg","orientation":"landscape"},"medium":{"height":267,"width":400,"url":"http://example.com/wp-content/uploads/2017/04/web-400x267.jpg","orientation":"landscape"},"large":{"height":441,"width":660,"url":"http://example.com/wp-content/uploads/2017/04/web-1024x684.jpg","orientation":"landscape"},"full":{"url":"http://example.com/wp-content/uploads/2017/04/web.jpg","height":1200,"width":1796,"orientation":"landscape"}},"mime":"image/jpeg","type":"image","subtype":"jpeg","id":3589,"url":"http://example.com/wp-content/uploads/2017/04/web.jpg","alt":"","link":"http://example.com/web/","caption":""}];


var result = _.map(array, v => ({"alt":v.alt, "caption":v.caption, "id":v.id, "url":v.sizes.thumbnail.url}));

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

Upvotes: 0

Anurag Awasthi
Anurag Awasthi

Reputation: 6233

You can use plain js,

function pickfromobject(object, key){
	var parts= key.split('.')
	if(parts.length > 1){
		var tempkey = parts.shift()
		if(!object[tempkey]){
			return null
		} else{
			return pickfromobject(object[tempkey], parts.join('.'))
		}
	} else{
		return object[parts[0]]
	}
}


function pick(arr, key){
	var result = []
	for(var i =0;i<arr.length; i++){
		result.push({[key]: pickfromobject(arr[i], key)})
	}
	return result
}

var a = [{a: {c:{d:1}}, b:2}, {a:{c:{d:3}}, b:3}]

console.log(pick(a, 'a.c.d'))

Upvotes: -3

Related Questions