Home > Mobile >  In an object nesting key-value pairs, how to convert a single-value array into just the value itself
In an object nesting key-value pairs, how to convert a single-value array into just the value itself

Time:02-14

Given an array that nests inner objects which have key-value pairs, I want to convert single-element-arrays to just the value itself.

So let's say that we have the following albums array:

const albums = [
    {
        "band": ["beetles"],
        "album": ["yellow_submarine"],
        "year": [1969]
    },
    {
        "band": [ "coldplay"],
        "album": ["Parachutes"],
        "year": [2000]
    },
    {
        "band": ["nirvana"],
        "album": ["nevermind"],
        "year": [1991]
    }
]

Since all the arrays are single-values, I would like to convert this entire albums object to:

// desired output
[
    {
        "band": "beetles",
        "album": "yellow_submarine",
        "year": 1969
    },
    {
        "band": "coldplay",
        "album": "Parachutes",
        "year": 2000
    },
    {
        "band": "nirvana",
        "album": "nevermind",
        "year": 1991
    }
]

I've seem lots of posts discussing the opposite (i.e., how to convert a single value into an array), but could not find an answer to this current question. Maybe I'm not using the correct search terms...

CodePudding user response:

If you want to create a new array of new objects, you'd use map along with creating new objects unwrapping their values. You have a couple of options for how to handle the objects. You could use Object.fromEntries and Object.entries:

const updatedAlbums = albums.map(album =>
    Object.fromEntries(
        Object.entries(album).map(([key, value]) => [key, value[0]])
    )
);

Live Example:

const albums = [
    {
        "band": ["beetles"],
        "album": ["yellow_submarine"],
        "year": [1969]
    },
    {
        "band": [ "coldplay"],
        "album": ["Parachutes"],
        "year": [2000]
    },
    {
        "band": ["nirvana"],
        "album": ["nevermind"],
        "year": [1991]
    }
];

const updatedAlbums = albums.map(album =>
    Object.fromEntries(
        Object.entries(album).map(([key, value]) => [key, value[0]])
    )
);

console.log(updatedAlbums);
.as-console-wrapper {
    max-height: 100% !important;
}

Or you could use an inner loop to avoid intermediary arrays:

const updatedAlbums = albums.map(album => {
    const newAlbum = {};
    for (const key in album) {
        if (Object.hasOwn(album, key)) {
            newAlbum[key] = album[key][0]; // Unwrapping the value
        }
    }
    return newAlbum;
});

Live Example:

const albums = [
    {
        "band": ["beetles"],
        "album": ["yellow_submarine"],
        "year": [1969]
    },
    {
        "band": [ "coldplay"],
        "album": ["Parachutes"],
        "year": [2000]
    },
    {
        "band": ["nirvana"],
        "album": ["nevermind"],
        "year": [1991]
    }
];

// Quick-and-dirty polyfill for environments that don't have `Object.hasOwn` yet
if (!Object.hasOwn) {
    Object.hasOwn = Function.prototype.call.bind(Object.prototype.hasOwnProperty);
}

const updatedAlbums = albums.map(album => {
    const newAlbum = {};
    for (const key in album) {
        if (Object.hasOwn(album, key)) {
            newAlbum[key] = album[key][0]; // Unwrapping the value
        }
    }
    return newAlbum;
});

console.log(updatedAlbums);
.as-console-wrapper {
    max-height: 100% !important;
}

CodePudding user response:

Map albums to a new array of objects, use a unArray method within the map -lambda

const albums = [{
    "band": ["beetles"],
    "album": ["yellow_submarine"],
    "year": [1969]
  },
  {
    "band": ["coldplay"],
    "album": ["Parachutes"],
    "year": [2000]
  },
  {
    "band": ["nirvana"],
    "album": ["nevermind"],
    "year": [1991]
  }
];

// Note: for a true copy of albums and its arrays,
// the values must be spreaded (e.g. ...album.band)
const noArrays = albums.map(album => {
  const unArray = v => v.length === 1 ? v.shift() : v;
  return { ...{},
    band: unArray(...album.band),
    album: unArray(...album.album),
    year: unArray(...album.year)
  };
});

console.log(noArrays);
.as-console-wrapper {
  max-height: 100% !important;
}

If the keys of the albums entries are not (all) known, using a reducer for all album entries would be more generic:

const albums = [{
    "band": ["beetles"],
    "album": ["yellow_submarine"],
    "year": [1969]
  },
  {
    "band": ["coldplay"],
    "album": ["Parachutes"],
    "year": [2000]
  },
  {
    "band": ["nirvana"],
    "album": ["nevermind"],
    "year": [1991]
  }
];

// Note: for a true copy of albums and its arrays,
// the values ust be spreaded (i.e ...value)
const noArrays = albums.map( album => {
  const unArray = v => v.length === 1 ? v.shift() : v;
  return Object.entries(album).reduce( (acc, [key, value]) => 
    ({...acc, [key]: unArray(...value)}), {});
});

console.log(noArrays);

CodePudding user response:

Edit: This changes the value in place rather than creating a new dictionary with the final result.

for (var i = 0; i < albums.length; i  ) {
   for (var key in albums[i]) {
      albums[i][key] = albums[i][key][0];
   }
}

CodePudding user response:

Keep it Simple! You can achieve this by just using Array.toString() method.

Working Demo :

const albums = [
    {
        "band": ["beetles"],
        "album": ["yellow_submarine"],
        "year": [1969]
    },
    {
        "band": [ "coldplay"],
        "album": ["Parachutes"],
        "year": [2000]
    },
    {
        "band": ["nirvana"],
        "album": ["nevermind"],
        "year": [1991]
    }
];

albums.forEach((obj) => {
    Object.keys(obj).forEach((key) => {
    obj[key] = obj[key].length === 1 ? obj[key].toString() : obj[key]
  });
});

console.log(albums);

  • Related