A more efficient way to rearrange Array of Objects? - javascript

Hello fellow good devs,
I want to rearrange this the Array of objects (array1) into the same order given in array2; as you may have noticed below, array2 is a simple array which its values are the same key names in array1, so you can say array2 is the 'arranging reference' for array1.
The below code worked for me as expected, but I am not happy with it, so much loops inside loops, i am afraid it may not be efficient.
I thought of using map() but I couldn't figure out how, is there any more efficient way for doing that by using map() or some other method?
Note: This is a server-side code, so I am not concerned about Browser compatibility.
var array1 =
[
{ 'aaa': '1000', 'bbb': '2000' },
{ 'aaa': '3333', 'bbb': '4444' }
]
var array2 = ['bbb', 'aaa'];
var reArrangedArr = [];
array1.forEach(x => {
var obj = {};
for (i = 0; i < array2.length; i++) {
for (key in x) {
console.log(array2[i] + " " + key)
if (array2[i] === key) {
newKey = array2[i];
console.log("equal");
obj[newKey] = x[key]
}
}
}
reArrangedArr.push(obj);
});
console.log(reArrangedArr);
///output: > Array [Object { bbb: "2000", aaa: "1000" }, Object { bbb: "4444", aaa: "3333" }]

You could map the array and map with Object.assign the keys and their values in the wanted order.
With spread syntax ..., a given iterable, like an array or string, is treated as parameters for the function call. Basically it is a syntactic suggar for function.apply(this, array).
var data = [{ aaa: '1000', bbb: '2000' }, { aaa: '3333', bbb: '4444' }],
keys = ['bbb', 'aaa'],
reordered = data.map(o => Object.assign(...keys.map(k => ({ [k]: o[k] }))));
console.log(reordered);
.as-console-wrapper { max-height: 100% !important; top: 0; }

You can use Array.reduce() operation to achieve that:
var array1 = [
{ 'aaa': '1000', 'bbb': '2000' },
{ 'aaa': '3333', 'bbb': '4444' }
];
var array2 = ['bbb', 'aaa'];
var reArrangedArr = array1.reduce((acc, obj) => {
var tempObj = {};
array2.forEach(item => tempObj[item] = obj[item]);
acc.push(tempObj);
return acc;
},
[]);
console.log(reArrangedArr);

Related

Comparing one value from two arrays if bigger then copying + combining into third array

I'm trying to make a simple app to update prices in WooCommerce through the REST API.
I have arrayOne which has SKU + updated prices from my ERP
[
{sku=PD-1000-B, price=9800.00},
{sku=PD-1007-A, price=9678.16}
]
arrayTwo which has all products from woocommerce, SKU, id (which I need to get) and current price
[
{sku=PD-1000-B, id=1622.0, price=8145.9},
{sku=PD-1007-A, id=1624.0, price=9678.16}
]
I would like to compare arrayTwo with arrayOne, if price in arrayOne is bigger then with all coincidences combine and create new array. Something like this
[
{sku=PD-1000-B, id=1622.0, price=9800.00}
]
Since the only bigger price is for PD-1000-B.
All I got so far is to create a new Set but that doesn't compare anything, the idea would be to reduce only to changes the amount to update.
EDIT: As of right now I'm merely replacing the price in arrayTwo with the one in arrayOne using this:
let set = new Set();
for (let i = 0; i < data.length; i++)
set.add(data[i]['sku'])
for (let i = 0; i < container.length; i++)
if (set.has(container[i]['sku']))
container[i]['price'] = data[i]['price'];
container is an empty variable I'm using to collect the data I get from WooCommerce as an array and data is a the array which contains the updated prices + sku.
Thank you.
You can achieve this in two steps:
Find greatest ones of each in arrOne
Compare with corresponding one in arrTwo
You can use this nice function for that:
const arrOne = [
{
sku: "PD-1000-B",
price: 9678.16
},
{
sku: "PD-1000-B",
price: 9800.00
},
{
sku: "PD-1007-C",
price: 9714.16
},
{
sku: "PD-1007-C",
price: 9270.00
}
]
const arrTwo = [
{sku: "PD-1000-B", id:1622.0, price:8145.9},
{sku: "PD-1007-A", id:1624.0, price:9678.16},
{sku: "PD-1007-C", id:1627.0, price:9478.16},
]
const findAllHighest = (arr) => {
// 1) get highest one of each in arrOne
const arrOneGreatest = arr.reduce((prev, cur) => {
if(!prev[cur.sku]){
prev[cur.sku] = cur
return prev
}
if(cur.price > prev[cur.sku].price){
prev[cur.sku] = cur
}
return prev
}, {})
// match to arrayTwo
const result = arrTwo.map(el => {
const arrOneObj = Object.values(arrOneGreatest).find(n => n.sku === el.sku)
if(!arrOneObj)
return el
if(arrOneObj.price > el.price)
el.price = arrOneObj.price
return el
}, [])
return result
}
console.log(findAllHighest(arrOne))
.as-console-wrapper { max-height: 100% !important; top: 0; }
I'd try it this way:
var arrayOne = [
{sku: 'PD-1000-B', price: 9800.00},
{sku: 'PD-1007-A', price: 9678.16}
];
var arrayTwo = [
{sku: 'PD-1000-B', id: 1622.0, price: 8145.9},
{sku: 'PD-1007-A', id: 1624.0, price: 9678.16}
];
// convert the array into the object {sku1: {}, sku2: {}, ...}
var arrayOne_obj = {}
for (let obj of arrayOne)
arrayOne_obj[obj.sku] = {'price': obj.price};
// convert the array into the object {sku1: {}, sku2: {}, ...}
var arrayTwo_obj = {}
for (let obj of arrayTwo)
arrayTwo_obj[obj.sku] = {'price': obj.price, 'id': obj.id};
// loop through the 'sku'-subobjects of the 'arrayOne_obj' object
// compare its prices with prices of the same 'sku'-subobject of 'arrayTwo_obj',
// and make the output array
var output = [];
for (let sku in arrayOne_obj) {
let subObjOne = arrayOne_obj[sku];
let subObjTwo = arrayTwo_obj[sku];
if (subObjOne.price > subObjTwo.price) {
output.push({'sku':sku, 'id': subObjTwo.id, 'price':subObjOne.price});
}
}
console.log(output); // output [ {sku: 'PD-1000-B', id:1622.0, price:9800.00} ]
.as-console-wrapper { max-height: 100% !important; top: 0; }

What is the best way to access key/values of a object array when I don't know them?

I have this array above and I need every property of it
let arr = [{'John': 0}, {'Doe': 50}, {'Marry': 100}]
How could I extract every single key/value of it, once in theory, I don't know any of them?
I have already tried using object.keys but it returns the indexes of my array.
This should work
const arr = [{'John': 0}, {'Doe': 50}, {'Marry': 100}];
// to iterate over each element in the arry
arr.forEach(a => {
// To Iterate over each key in the element object
Object.keys(a).forEach(k => {
// to print the value of the 'k' key
console.log(k + ' : ' + a[k]);
})
})
1) You can use flatMap and Object.keys to get keys from an array of objects.
let arr = [{ John: 0 }, { Doe: 50 }, { Marry: 100 }];
const result = arr.flatMap((o) => Object.keys(o));
console.log(result);
2) To find all values in an array
let arr = [{ John: 0 }, { Doe: 50 }, { Marry: 100 }];
const values = arr.flatMap((o) => Object.values(o));
console.log(values);
3) If you want to find out all keys and values in an object
let arr = [{ John: 0 }, { Doe: 50 }, { Marry: 100 }];
const result = {
keys: [],
values: [],
};
for (let obj of arr) {
Object.entries(obj).map(([k, v]) => {
result.keys.push(k);
result.values.push(v);
});
}
console.log(result);
If you want to collect all the keys and values of a nested array of objects, you can use Array.prototype.reduce and then collect the keys and values of the nested objects in separate nested arrays, using Object.keys() and Object.values() respectively:
const arr = [{'John': 0}, {'Doe': 50}, {'Marry': 100}];
const allKeysAndValues = arr.reduce((acc, cur) => {
acc.keys.push(...Object.keys(cur));
acc.values.push(...Object.values(cur));
return acc;
}, { keys: [], values: [] });
console.log(allKeysAndValues);
A one liner could be
let arr = [{'John': 0}, {'Doe': 50}, {'Marry': 100}]
console.log( arr.map( obj => Object.entries(obj)));

Converting an array of 3 arrays into 1 big array with object variable

I'm new to StackOverflow and I know this post might possibly be a duplicate of another so please spare me with all the downvotes and if you think there's an answer to my question out there, please post it and I'll delete this question. Thanks for understanding.
var array1 = ["name", "title", "desc"]
var array2 = [["name1", "name2"], ["title1", "title2"],["desc1", "desc2"]]
How will I turn these into:
[
{name: "name1", title: "title1", desc: "desc1"},
{name: "name2", title: "title2", desc: "desc2"}
]
You can use Array#map, Object.assign (with spread syntax) and the ES6 computed property syntax to achieve that:
const array1 = ["name", "title", "desc"],
array2 = [["name1", "name2"], ["title1", "title2"],["desc1", "desc2"]];
const result = array2[0].map( (_, j) =>
Object.assign(...array1.map( (key, i) => ({ [key]: array2[i][j] }) ))
);
console.log(result);
.as-console-wrapper { max-height: 100% !important; top: 0; }
const result = [];
for(const [index, key] of array1.entries()){
for(const [userindex, value] of array2[index].entries()){
if(!result[userindex])
result[userindex] = {};
result[userindex][key] = value;
}
}
You might go over every key and the values related to the key and assign every key/value pair to the resulting object at the position of the value.
You could reduce the given values array by using the keys as key and the value for new objects.
var keys = ["name", "title", "desc"],
values = [["name1", "name2"], ["title1", "title2"],["desc1", "desc2"]],
objects = values.reduce((r, a, i) => {
a.forEach((v, j) => Object.assign(r[j] = r[j] || {}, { [keys[i]]: v }));
return r;
}, []);
console.log(objects);
You can use this way also:
var array1 = ["name", "title", "desc"];
var array2 = [["name1", "name2"], ["title1", "title2"],["desc1", "desc2"]];
var res = [];
for(var i=0; i<array2[0].length; i++){
var obj = {};
for(var j=0; j<array1.length; j++){
var key = array1[j];
var value = array2[j][i];
obj[key] = value;
}
res.push(obj);
}
console.log(res);

Update Array containing objects using spread operator

I have an array containing objects in javascript / typescript.
let array = [{id:1,name:'One'}, {id:2, name:'Two'}, {id:3, name: 'Three'}]
How can I update name of the second element (with id 2) and copy the array to a new array using javascript spread (...) operator?
You can use a mix of .map and the ... spread operator
You can set the value after you've created your new array
let array = [{id:1,name:'One'}, {id:2, name:'Two'}, {id:3, name: 'Three'}];
let array2 = array.map(a => {return {...a}})
array2.find(a => a.id == 2).name = "Not Two";
console.log(array);
console.log(array2);
.as-console-wrapper { max-height: 100% !important; top: 0; }
Or you can do it in the .map
let array = [{id:1,name:'One'}, {id:2, name:'Two'}, {id:3, name: 'Three'}];
let array2 = array.map(a => {
var returnValue = {...a};
if (a.id == 2) {
returnValue.name = "Not Two";
}
return returnValue
})
console.log(array);
console.log(array2);
.as-console-wrapper { max-height: 100% !important; top: 0; }
Using Spred Operator, you can update particular array value using following method
let array = [
{ id: 1, name: "One" },
{ id: 2, name: "Two" },
{ id: 3, name: "Three" },
];
const label = "name";
const newValue = "Two Updated";
// Errow comes if index was string, so make sure it was integer
const index = 1; // second element,
const updatedArray = [
...array.slice(0, index),
{
// here update data value
...array[index],
[label]: newValue,
},
...array.slice(index + 1),
];
console.log(updatedArray);
There are a few ways to do this. I would suggest using Array.map :
let new_array = array.map(element => element.id == 2 ? {...element, name : 'New Name'} : element);
or with Object.assign :
let new_array = array.map(element => element.id == 2 ? Object.assign({}, element, {name : 'New Name'}) : element);
Map returns a new array, so you shouldn't need the array spread operator.
We can use
let array = [{id:1,name:'One'}, {id:2, name:'Two'}, {id:3, name: 'Three'}];
let array2 = [...array]
array2.find(a => a.id == 2).name = "Not Two";
console.log(array2);
You can simply use map() and change the element there.
here is the code---
array_copy = array.map((element) => {
console.log(element.id);
if (element.id === 2) {
element.name = "name changed";
}
return element;
});
console.log(array_copy);
Here the main array also gets modified, as elements inside the array are objects and it references to the same location even in the new array.
You can do it like this in map, no need for spread:
const array = [{id:1,name:'One'}, {id:2, name:'Two'}, {id:3, name: 'Three'}]
const updatedArray = array.map(a => {
if (a.id == 2) {
a.name = 'New Name';
}
return a;
});
Merging properties from filterQueryParams to selectedLaws (existing solutions did not suit me):
if (this.filterQueryParams && Object.prototype.toString.call(this.filterQueryParams) === '[object Array]') {
for (const law of this.filterQueryParams) {
if (law as Laws.LawDetail) {
const selectedLaw = this.selectedLaws.find(x => x.languageCode === law.languageCode);
if (selectedLaw) {
for (const propName of Object.keys(law)) {
selectedLaw[propName] = law[propName];
}
}
else {
this.selectedLaws.push(law);
}
}
}
}
import React,{useState} from 'react';
export function App(props) {
const[myObject,setMyObject] = useState({
"Name":"",
"Age":""
});
const[myarray, setmyarray] = useState([]);
const addItem =() =>{
setMyObject({...myObject,"Name":"Da","Age":"20"});
setmyarray([...myarray, 1]);
};
console.log(myarray);console.log(myObject);
return (
<div className='App'>
<h1>Hello React.</h1>
<h2>Start editing to see some magic happen!</h2>
<button onClick={addItem}>Add me</button>
</div>
);
}
// Log to console
console.log('Hello console')
let array = [{id:1,name:'One'}, {id:2, name:'Two'}, {id:3, name: 'Three'}];
let array2 =[...array.slice(0, 0), Object.assign({}, array[0], {
name:'new one' //change any property of idx
}),...array.slice(0 + 1)]
console.log(array);
console.log(array2);
[...array.slice(0, idx), Object.assign({}, array[idx], {
x:new_x //change any property of idx
}),...array.slice(idx + 1)]

Changing the case of JavaScript object keys

I have following object.
var obj = [{
Address1: "dd",
Address2: "qww",
BankAccNo: "44",
BankBranchCode: "44",
BloodGrp: "A+"
},
{
Address1: "dd",
Address2: "qww",
BankAccNo: "44",
BankBranchCode: "44",
BloodGrp: "A+"
}];
How can I make all of the keys uppercase?
I want to be able to access values like this : - obj[0].ADDRESS1
obj = obj.map( function( item ){
for(var key in item){
var upper = key.toUpperCase();
// check if it already wasn't uppercase
if( upper !== key ){
item[ upper ] = item[key];
delete item[key];
}
}
return item;
});
http://jsfiddle.net/07xortqy/
Loop over all the properties in the object (with for in)
Use .toUpperCase() to get the uppercase version of the property name
Copy the value from the original property to the uppercase version
delete the original property
For anyone looking for a solution working with objects, arrays, and nested objects or arrays:
// rename function depending on your needs
const capitalizeKeys = (obj) => {
const isObject = o => Object.prototype.toString.apply(o) === '[object Object]'
const isArray = o => Object.prototype.toString.apply(o) === '[object Array]'
let transformedObj = isArray(obj) ? [] : {}
for (let key in obj) {
// replace the following with any transform function
const transformedKey = key.replace(/^\w/, (c, _) => c.toUpperCase())
if (isObject(obj[key]) || isArray(obj[key])) {
transformedObj[transformedKey] = capitalizeKeys(obj[key])
} else {
transformedObj[transformedKey] = obj[key]
}
}
return transformedObj
}
const t = {
test1: 'hello',
test2: {
aa: 0,
bb: '1',
cc: [ 3, '4', 'world']
},
test3: [{
aa: 5,
bb: '6'
}, {
cc: [ 'hello', 'world', 7 ]
}
]
}
console.log(JSON.stringify(capitalizeKeys(t)))
(this function is to be adapted since I only had to capitalize the first letter, and there is no need for the helper functions to be nested)
$.each(obj, function(i, parent) {
$.each(parent, function(key, record) {
parent[ key.toUpperCase() ] = record[key]; //rename key
delete parent[key]; //delete old key
});
});
let obj = [
{ Address1: "dd",Address2: 'qww',BankAccNo: 44,BankBranchCode: 44,BloodGrp: 'A+' },
{ Address1: "dd",Address2: 'qww',BankAccNo: 44,BankBranchCode: 44,BloodGrp: 'A+' }
];
const uppercaseKeys = (elem) => {
let newObject = {}
Object.keys(elem).reduce( (acc, key, allKeys) => {
acc[key.toUpperCase()] = elem[key]
delete elem[key]
return acc
}, elem)
return newObject
}
obj.forEach( o => uppercaseKeys )
console.log(obj)
You can now also use Object.fromEntries() in combination with Object.entries() - have a look at the Object transformations section.
const obj2 = obj1.map(item => Object.fromEntries(Object.entries(item).map(([key, val]) => [
key.toUpperCase(),
val
])));
I've detailed the steps below:
// Iterate through each item in array
const obj2 = obj1.map(item => {
// Object.entries() method returns array of object's own enumerable string-keyed property [key, value] pairs,
// in the same order as that provided by a for...in loop
const entries = Object.entries(item);
// Convert keys to uppercase
const uppercaseEntries = entries.map(([key, val]) => [
key.toUpperCase(),
val
]);
// Object.fromEntries() method transforms a list of key-value pairs into an object.
return Object.fromEntries(uppercaseEntries);
});`
https://jsfiddle.net/buj5y32x/3/
For wider support, you are better off using Object.keys() with Array.reduce().
const obj2 = obj1.map(item =>
Object.keys(item).reduce((accumulator, key) => {
// accumulator is the new object we are creating
accumulator[key.toUpperCase()] = item[key];
return accumulator;
}, {})
);
https://jsfiddle.net/qf81ezsy/
You could just loop through them and add new entries?
for (index in obj) {
for (key in obj[index]) {
obj[index][key.toUpperCase()] = obj[key];
}
}

Categories

Resources