3

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

3 Answers 3

10

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>

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

2 Comments

You deserve a medal for this!
deep pick... sorry makes me laugh haha
0

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>

Comments

-3

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'))

2 Comments

This I think is a very verbose example that includes way more surface area for bugs. Use a Lodash or underscore option would be preferred in most any case
"plain js" is usually called "VanillaJs".

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.