Maintaining order of items in the map function: Javascript - javascript

I am trying to use the map to change the one of the field name , but I see the order of items are getting changed .
var arrOfObj = [
{
name: "test1",
value: "value1"
},
{
name: "test2",
value: "value2"
}
];
function changeKeyName(arr, oldValue, newVal) {
return arr.map(item => {
item[`${newVal}`] = item[`${oldValue}`];
delete item[`${oldValue}`];
return item;
});
}
console.log(changeKeyName(arrOfObj, "name", "type"));
Is there any way I can maintain the order of items along with changing of one of the field names.
O/P:
[{type:"test1",value: "value1"}, {type: "test2", value:"value2"}]
Thanks in advance

You can use Object.entries to take an array of entries, then map them, replacing the old key with the new key when found:
var arrOfObj = [
{
name: "test1",
value: "value1"
},
{
name: "test2",
value: "value2"
}
];
const changeKeyName = (arr, oldKey, newKey) => arr.map(
item => Object.fromEntries(
Object.entries(item).map(
([key, val]) => [key === oldKey ? newKey : key, val]
)
)
);
console.log(changeKeyName(arrOfObj, "name", "type"));
(Contrary to popular belief, object property order is guaranteed by the specification, and has been implemented in all environments for years. But keep in mind that this will only work for keys which aren't array indicies - array indicies like 0 1 2 can't be ordered relative to other properties, they'll always be iterated over first, in ascending numeric order)
That said, code is generally easier to understand if it's written such that property order doesn't matter - if you have code that depends on the properties being in a particular order, I'd recommend refactoring it so that the property order doesn't matter.

map is being used incorrectly here as you should always return a new set of results from that.
You can do this and you can change the order as required:
const arrOfObj = [
{
name: "test1",
value: "value1"
},
{
name: "test2",
value: "value2"
}
];
function changeKeyName(arr, oldValue, newVal) {
return arr.map(({ [oldValue]: val, ...rest }) => {
return {
[newVal]: val,
...rest,
};
});
}
console.log(changeKeyName(arrOfObj, "name", "type"));

Related

How to convert objects inside array to nested array JavaScript?

I have an array containing objects that every element but the last one are objects, but I want to convert them into an array of arrays and add the last element.
To be more explicit here is how I have it:
[
{ 0: [1,2], 1: [6,2], name: "" },
{ 0: [3,4], 1: [2,2], name: "" }
]
and the result I want is this one:
[
{ multipolygon: [ [1,2], [6,2] ], name: ""},
{ multipolygon: [ [3,4], [2,2] ], name: ""}
]
Each single array contained inside the original array is converted into an array of those arrays.
I have tried doing this:
const zonesArray = zones.map(el => Object.values(el)) // obj => array
const polygons = zonesArray.filter(el => el.pop()) // array without name
to get all the arrays contained inside the obj but then I realized how can I replace this into the original objects.
I have tried to modify the groupBy function found on MDN:
function groupBy(objectArray, property) {
return objectArray.reduce(function (acc, obj) {
let key = obj[property]
if (!acc[key]) {
acc[key] = []
}
acc[key].push(obj)
return acc
}, {})
}
But I can't seem to find the answer
It doesn't look like you're trying to group by a property, you're trying to transform each object in the array separately - which can be done by taking the name and the numeric properties together when mapping, then returning the shape of the new object:
const arr = [
{ 0: [1,2], 1: [6,2], name: "" },
{ 0: [3,4], 1: [2,2], name: "" }
];
const result = arr.map(({ name, ...rest }) => ({
name,
multipolygon: Object.values(rest)
}));
console.log(result);

How to ensure a certain key value pair in Typescript Object remains at the last position

I need to create a Typescript Object in which a certain element with the key 'NONE' always remains at last. I need this to ensure that while rendering this object in my HTML page its value appears at bottom.
So basically I need an implementation of myObject.shiftKeyToLastPosition(keyname);
I've tried deleting and re-appending and reduce method. That didn't help.
If all your properties are string, you could try this
const source = {
'Domestic': '1',
'NONE': '0',
'Wild': '2',
};
const { NONE, ...dest } = source;
dest.NONE = source.NONE;
console.log(dest);
Here we are creating a new object without the NONE key and then adding NONE key at the last.
As per ECMAScript 2015 spec, the traversal of an object with string keys would yield keys in order of insertion.
P.S: Assuming that you have only integer and string keys, no Symbol keys.
As pointed out by proxima-b, there's no way to deterministically order an object.
What you can do though, is create an helper function that lets you define the order in which you'd like to display the key/values. The cool thing with Typescript is that you can do that in a type safe way!
const myObject = {
'hello3': 'Value 3',
'hello1': 'Value 1',
'hello2': 'Value 2',
'hello4': 'Value 4',
} as const;
function orderObjectToArrayKeyValue<Obj>(obj: Obj, orderKeys: { [key in keyof Obj]: number }): { key: keyof Obj, value: Obj[keyof Obj] }[] {
return Object
.entries<number>(orderKeys)
.sort(([, order1], [, order2]) => order1 < order2 ? -1 : 1)
.map(([key]) => ({ key, value: obj[key as keyof Obj] }) as { key: keyof Obj, value: Obj[keyof Obj] });
}
With the above example, if you call:
console.log(orderObjectToArrayKeyValue(myObject, {
hello1: 1,
hello2: 2,
hello3: 3,
hello4: 4,
}));
You'll get
[
{
"key": "hello1",
"value": "Value 1"
},
{
"key": "hello2",
"value": "Value 2"
},
{
"key": "hello3",
"value": "Value 3"
},
{
"key": "hello4",
"value": "Value 4"
}
]
Then using the framework of your choice, it'll be really easy to loop over that array and display the values (+ use the key if needed).
Here's a live example (press enter while focusing the left side and it'll run the code, the output will be displayed in your console).

Javascript - transform an object of array list to another format?

So I've been stumped on this for hours and I can't really figure out an elegant solution to solve this problem. Let's say I have this:
let Fields = {
GAME: [
{ code: '{{GTAV}}', title: { en: "grnti"} },
{ code: '{{GTA5}}', title: { en: "Grand theph " } },
]
};
How can I turn this into a new format that looks like this ?
let Fields = {
tags: [
{ name: 'GAME', tags:[
{ name: 'grnti', value: "{{GTAV}}" },
{ name: 'Grand theph', value: "{{GTA5N}}" }
]},
]};
I tried to create a function to do the job , but for some reason my brain cannot seem to grasp the solution. Any help please !
A simple version of this might look like the following:
const transform = (fields) => ({
mergeTags: Object .entries (fields) .map (([name, innerFields]) => ({
name,
mergeTags: innerFields .map (({code, title: {en}}) => ({name: en, value: code}))
}))
})
const fields = {RECIPIENT: [{code: '{{RECIPIENT.LN}}', title: {en: "name"}}, {code: '{{RECIPIENT.FN}}', title: {en: "first name" }}]}
console .log (transform (fields))
But from your nested mergeTags properties, I'm guessing that there is something recursive going on. If so, we need more information about the input and output structures.
i just threw a nested reduce function together.
const transformed = Object.entries(Fields).reduce((tags, [key, value]) => {
const mergedTags = value.reduce((codes, code) => {
codes.mergeTags.push({name: code.title.en, value: code.code});
return codes;
}, {name: key, mergeTags: []})
tags.mergeTags.push(mergedTags)
return tags;
}, {mergeTags: []})
Does that work for you?
It is hard to tell exactly from your question what you are hoping to accomplish as well as the shape of your data. Based on your question though, you would probably want to use the Object.keys and map functions
let Fields = {
RECIPIENT: [
{ code: '{{RECIPIENT.LN}}', title: { en: "name" } },
{ code: '{{RECIPIENT.FN}}', title: { en: "first name" } },
]
};
// gets the keys of the 'Fields' object(in this case only 'RECIPIENT'
let newFields = Object.keys(Fields)
// each key should create a new object with the 'key' from the original object as the 'name' of the new object
.map(key => ({
name: key,
// 'Fields[key]' gets the array from the 'RECIPIENT' property and then creates a new object from each object in the original array, mapping the 'title.en' property in the original object to 'name' in the new object and 'code' in the original object to 'value' in the new object
mergeTags: Fields[key].map(property => ({
name: property.title.en,
value: property.code
}))
}));
console.log(newFields);
Here's a clean way that may seem a bit like magic, but I'll walk you through what's going on.
let Fields = {
RECIPIENT: [
{ code: '{{RECIPIENT.LN}}', title: { en: "name"} },
{ code: '{{RECIPIENT.FN}}', title: { en: "first name" } },
]
};
const { pipe, fork, map, get } = rubico
const Transformed = pipe([
Object.entries, // { RECIPIENT: [...] } => [['RECIPIENT', [...]]
fork({
mergeTags: map(fork({ // iterate through each entry ['RECIPIENT', [...]]
name: get(0), // name is the item at index 0 of each entry
mergeTags: pipe([
get(1), // mergeTags starts with index 1 of each entry, the array of code+title objects
map(fork({ // iterate through the array of code + title objects and create new objects
name: get('title.en'), // name is title.en of each object
value: get('code'), // value is title.code of each object
})),
]),
})),
}),
])(Fields)
console.log(JSON.stringify(Transformed, null, 2))
<script src="https://unpkg.com/rubico"></script>
Disclaimer: I am the author of rubico
You can examine these methods in depth at the documentation

JSON manipulation - javascript - adding new keys and shifting data

I'm learning to manipulate JSON data and I am stuck trying to figure out how to cajole the following JSON into what I want as shown below:
Any pointers to function/terms/concepts that I should learn for this sort of problem would be greatly appreciated! Thanks
JSON object
{
car: 1,
van: 5,
cat: 99999999999999999999999
}
Desired outcome:
items: [
{ "type": "car", "value": "1"},
{ "type": "van", "value": "5"},
{ "type": "cat", "value": "99999999999999999999999"}
]
You can use a combination of Object.entries and Array.prototype.map:
const obj = { car: 1, van: 5, cat: 99999999999999999999999 };
let list = Object.entries(obj) // [["car",1],["van",5],["cat",99999999999999999999999]]
.map(x => ({ type: x[0], value: x[1] }));
console.log(list);
Or, with some destructuring:
const obj = { car: 1, van: 5, cat: 99999999999999999999999 };
let list = Object.entries(obj)
.map(([type, value]) => ({ type, value }));
console.log(list);
The callback to map:
([type, value]) => ({ type, value })
Expects an array as parameter: [type, value]. The first value in that array is assigned to type, the second one to value.
Then we use a shorthand form to set these values in our returned object:
=> ({ type, value })
I'm a beginner. I tried to solve the problem and this is the best I can come up with, tested in Node.js 10.
const obj = {"car": 1, "van": 5, "cat": 999999}
const items = []
for (let key in obj) {
items.push({"type": key, "value": obj[key]})
}
console.log(items)
One thing I am slightly confused about is the difference between for..in vs for..of, I'm currently looking into it.
Object.keys will return:
['car', 'van', 'cat'];
On this array you can use Array's map function which creates a new array with the results of calling a provided function on every element in the calling array.
var a = {
car: 1,
van: 5,
cat: 99999999999999999999999
}
m = Object.keys(a).map((v)=>{
return {
type: v,
value: a[v]
}
})
console.log(m);
#GustavMahler hope you understand. To learn more about array functions you should look map, reduce and filter.
This one uses object.keys
let js = {car:1, van:5, cat:9999}
Object.keys(js).map( x => ({type: x, value: js[x] }) )
[ { type: 'car', value: 1 },
{ type: 'van', value: 5 },
{ type: 'cat', value: 9999 } ]

acessing new object from Object.keys and forEach method javascript

I'm trying to create a new object (newobj) with new keys and props from a poorly structured existing array of object (arrays?) ex.
[{"product":["1009", "name", "price", "image", "description"]},
{"product":["1004", "name2", "price2", "image2", "description2"]}]
I'm getting result I want but newobj does not update outside of the scope of the forEach method (more than 1 result). My question is what am I not getting ? Is forEach incorrect method with this type obj?
var newobj = {};
Object.keys(oldobj).forEach(function(prop) {
newobj["id"] = Number(oldobj[prop]["product"][0]),
newobj["name"] = oldobj[prop]["product"][1],
newobj["price"] = Number(oldobj[prop]["product"][3]),
newobj["image"] = "url" + oldobj[prop]["product"][0] + ".jpg",
newobj["description"] = oldobj[prop]["product"][2];
// this works
// console.log(JSON.stringify(newobj));
});
// this only updated with one
app.locals.newobj = newobj;
I've also tried mapping (w/ underscore) but I have the same result, I can't access outside scope.
_.each(mappedobj, function(prop) {
_.each(prop["product"][0], function(vals){
newobj["id"] = Number(prop["product"][0]);
console.log(JSON.stringify(newobj));
});
});
If you want all the values from the old object, you need to make newobj an array of objects. You can use .map() to do this transformation.
Object and array destructuring is a convenient way to avoid all those hard-coded indexes. And by naming the parameter variables properly, you can use object literal shorthand to create the resulting objects more easily.
var oldobj = [{
"product": ["1009", "name", "price", "image", "description"]
},
{
"product": ["1004", "name2", "price2", "image2", "description2"]
}
];
var newobj = oldobj.map(({product: [id, name, price, url, description]}) =>
({id: Number(id), name, price: Number(price), url: `url${url}.jpg`, description})
);
console.log(newobj);
Try this
let newObject = _.map(oldObject, (item) => {
return {
id: item.product[0],
name: item.product[1],
price: item.product[2],
image: item.product[3],
description: item.product[4]
};
});
If you want to convert an array of poorly structured object to an array of well structured ones, you can use Array.prototype.map from VanillaJS:
const data = [
{"product": ["1009", "name", "120", "image", "description"]},
{"product": ["1004", "name2", "250", "image2", "description2"]},
{"product": ["1012", "name3", "85", "image3", "description3"]}
];
const products = data.map(({ product }) => {
const [id, name, price, image, description] = product;
return {
id: Number(id),
name,
price: Number(price),
image: `url${image}.jpg`,
description
};
});
console.log(products);

Categories