Change order of object properties based on array with indices (JavaScript) - javascript

I've been really struggling with this piece of code.
I have an object that goes like:
var obj = {
Name: 'Test',
Id: 1,
Address: 'addr'
}
And an array that goes like:
var arr = [1,0,2];
I want the properties of the object to be sorted with the indices given in the second one.
The result should then be something like:
var obj = {
Id: 1,
Name: 'Test',
Address: 'addr'
}
I'm really looking forward to your replies.

You cannot reliably set the order of the properties in an object. You will need to rethink your approach to this problem so that the order is handled by an array, not an object. The array can then be used to write code that accesses properties in a specific order, even though the object doesn't actually have them in that order.
For example:
const columns = ['Id', 'Name', 'Address'];
const data = [{
Name: 'Test',
Id: 1,
Address: 'addr'
}, {
Address: 'addr2',
Id: 1,
Name: 'Test2',
}];
let csv = columns.join(',') + '\n';
data.forEach(obj => {
const row = columns.map(propertyName => {
return obj[propertyName];
});
csv = csv + row.join(',') + '\n'
})
console.log(csv);

Related

How to parse an array of objects to a list of strings? (Javascript)

In my Vue application I have a list of objects looking like this:
const arr = [
{
id: 1,
name: 'Max',
grade: 3
},
{
id: 2,
name: 'Lisa',
grade: 2
}
];
Now I want every object in this array to be a single string for itself. I know there is JSON.stringifty but this makes my whole array to a string and not every single object.
So the result should be something like:
const arr = [
"{id:1,name:'Max',grade:3}",
"{id:2,name:'Max',grade:3}"
];
That would be
const myJsonArr = arr.map((v) => JSON.stringify(v))
you can try it
let array = arr.map(item=>JSON.stringify(item))

How to add elements in an object while traversing through an array using map?

I am having an array like this :
arr = [ {id:0,name:Mark} , {id:1,name:Ron}, {id:2,name:Henry}, {id:3,name:Rose}].
I want to create an object like this :
obj1 = { Mark:false, Ron:false, Henry:false, Rose:flase }
I am using map to traverse through the array like this
let obj1 = {};
obj1 = arr.map((item)=> {
obj1[item.name] = false;
})
How can I achieve the following result?
You could map entries and build an object from the pairs.
const
data = [{ id: 0, name: 'Mark' }, { id: 1, name: 'Ron' }, { id: 2, name: 'Henry' }, { id: 3, name: 'Rose' }],
result = Object.fromEntries(data.map(({ name }) => [name, false]));
console.log(result);
Object.fromEntries() is probably the best idea. But you could also use reduce, if you got more operations on the array and want to stick to the "pipe" approach.
const arr = [
{ id: 0, name: 'Mark' },
{ id: 1, name: 'Ron' },
{ id: 2, name: 'Henry' },
{ id: 3, name: 'Rose' }
];
const objA = arr
.reduce((previous, { name }) => ({ ...previous, [name]: false }), {});
const objB = arr
.reduce((previous, { name }) => {
previous[name] = false;
return previous;
}, {});
The spreach operation {...obj} for objA does effectivly copy the object on each extension, which might not be desirable. But the modern JavaScript engines simplify those expressions anyways.
objB is the more standard approach for me. One additional benefit, in regards to Object.fromEntries() is that you can have some form of standard or default object / settings, which you can use as the start of the reduce (the second parameter) and evaluate in the collection function.
All three options are valid and depend on your code style.

Find duplicate names within an array of different files

A bit of a different use case from the ones I was suggested above.
I need to loop through and check each file name within an array of files and push the files that have the same name into a new array so that I can upload them later separately.
This is my code so far, and surely I have a problem with my conditional checking, can somebody see what I am doing wrong?
filesForStorage = [
{id: 12323, name: 'name', ...},
{id: 3123, name: 'abc', ...},
{id: 3213, name: 'name', ...},
...
]
filesForStorage.map((image, index) => {
for (let i = 0; i < filesForStorage.length; i++) {
for (let j = 0; j < filesForStorage.length; j++) {
if (
filesForStorage[i].name.split(".", 1) ===. //.split('.', 1) is to not keep in consideration the file extension
filesForStorage[j].name.split(".", 1)
) {
console.log(
"----FILES HAVE THE SAME NAME " +
filesForStorage[i] +
" " +
filesForStorage[j]
);
}
}
}
Using map without returning anything makes it near on pointless. You could use forEach but that is equally pointless when you're using a double loop within - it means you would be looping once in the foreach (or map in your case) and then twice more within making for eye-wateringly bad performance.
What you're really trying to do is group your items by name and then pick any group with more than 1 element
const filesForStorage = [
{id: 12323, name: 'name'},
{id: 3123, name: 'abc'},
{id: 3213, name: 'name'}
]
const grouped = Object.values(
filesForStorage.reduce( (a,i) => {
a[i.name] = a[i.name] || [];
a[i.name].push(i);
return a;
},{})
);
console.log(grouped.filter(x => x.length>1).flat());
JavaScript has several functions which perform "hidden" iteration.
Object.values will iterate through an object of key-value pairs and collect all values in an array
Array.prototype.reduce will iterate through an array and perform a computation for each element and finally return a single value
Array.prototype.filter will iterate through an array and collect all elements that return true for a specified test
Array.prototype.flat will iterate through an array, concatenating each element to the next, to create a new flattened array
All of these methods are wasteful as you can compute a collection of duplicates using a single pass over the input array. Furthermore, array methods offer O(n) performance at best, compared to O(1) performance of Set or Map, making the choice of arrays for this kind of computation eye-wateringly bad -
function* duplicates (files) {
const seen = new Set()
for (const f of files) {
if (seen.has(f.name))
yield f
else
seen.add(f.name, f)
}
}
const filesForStorage = [
{id: 12323, name: 'foo'},
{id: 3123, name: 'abc'},
{id: 3213, name: 'foo'},
{id: 4432, name: 'bar'},
{id: 5213, name: 'qux'},
{id: 5512, name: 'bar'},
]
for (const d of duplicates(filesForStorage))
console.log("duplicate name found", d)
duplicate name found {
"id": 3213,
"name": "foo"
}
duplicate name found {
"id": 5512,
"name": "bar"
}
A nested loop can be very expensive on performance, especially if your array will have a lot of values. Something like this would be much better.
filesForStorage = [
{ id: 12323, name: 'name' },
{ id: 3123, name: 'abc' },
{ id: 3213, name: 'name' },
{ id: 3123, name: 'abc' },
{ id: 3213, name: 'name' },
{ id: 3123, name: 'random' },
{ id: 3213, name: 'nothing' },
]
function sameName() {
let checkerObj = {};
let newArray = [];
filesForStorage.forEach(file => {
checkerObj[file.name] = (checkerObj[file.name] || 0) + 1;
});
Object.entries(checkerObj).forEach(([key, value]) => {
if (value > 1) {
newArray.push(key);
}
});
console.log(newArray);
}
sameName();

Output one value into an array from an array of Objects containing value pairs

Ive been trying combinations but can't figure this out. I am trying to pull out an array containing just the values from a value pair within an array containing objects.
INPUT
const myUsers = [
{ id: '1', name: 'bob' },
{ id: '56', name: 'bert' },
{ id: '32', name: 'Jenny' }
]
REQUIRED OUTPUT
[1,56,32]
CURRENT CODE
const idRecordsOnly = myUsers.map(item => {
const container = {};
container[item.id] = container[item.id]
return container;
})
console.log(idRecordsOnly)
Thanks Aurabliss! the answer is below
const idRecordsOnly = myUsers.map(item =>item.id)

Old JSON value Changed

I have two JSON objects columnsData and columns when assigning columnsData value to columns both values are changed.
var columnsData = [
{id: "id"},
{id: "root_task_assignee"},
{id: "root_task_id"},
{id: "root_task_status"},
{id: "root_task_tracker"},
{id: "rt_category"},
{id: "rt_priority"},
{id: "rt_subject"},
]
var columns = [];
using the below function I assigned the columnsData value to columns object, and also added some additional fields
for(i = 0;i < columnsData.length; i++){
columns[i] = columnsData[i];
columns[i]["name"] = columnsData[i]["name"] || columnsData[i]["id"];
columns[i]["type"] = columnsData[i]["id"]["type"] || "string";
}
but after assigning both have the same values. How the old JSON columnsData value was changed? is there any other way to assign values
columns[i] = columnsData[i] does not copy the data, it makes an additional reference to the same data.
For example, say you give Mr. Random Jones a nickname, "Cozy". If you give Cozy an envelope to hold, are you surprised if Mr. Jones is now holding an envelope too?
Same thing here. If you change columns[i], you are also changing columnsData[i], since they are the same object.
You would have to clone it if you wanted to have them be different. In this case, you just have to make a new object with id:
columns[i] = { id: columnsData[i].id };
In general, you would do well to find a nice clone function.
If it is required to keep original array pure (unchanged) we should use map method of array.
var columnsData = [
{id: "id"},
{id: "root_task_assignee"},
{id: "root_task_id"},
{id: "root_task_status"},
{id: "root_task_tracker"},
{id: "rt_category"},
{id: "rt_priority"},
{id: "rt_subject"},
]
var columns = columnsData.map(function(obj){
var rObj = {};
rObj[obj.key] = obj.value;
rObj["name"] = obj.value;
.....
return rObj;
});
Logic can be added in map method to create new array as required. Hope it helps.
columns[i] = columnsData[i] will not copy content from one object to another but it will an reference of the columnsData[i]. As they are refereeing to same object, change in property of one object will affect the primary object which is being refereed.
Try this:
var columnsData = [{
id: "id"
}, {
id: "root_task_assignee"
}, {
id: "root_task_id"
}, {
id: "root_task_status"
}, {
id: "root_task_tracker"
}, {
id: "rt_category"
}, {
id: "rt_priority"
}, {
id: "rt_subject"
}, ]
var columns = [];
for (i = 0; i < columnsData.length; i++) {
var obj = {};
obj["name"] = columnsData[i]["name"] || columnsData[i]["id"];
obj["type"] = columnsData[i]["id"]["type"] || "string";
columns.push(obj)
}
alert(JSON.stringify(columns));
alert(JSON.stringify(columnsData));

Categories

Resources