Javascript concat and prefix or rename props - javascript

I have two arrays that I am concatinating.
However each of these arrays has same property name I want to leave by adding prefix to each.
Array A(aData) looks like
[
{
id: 1,
title: `title`
code: '34x'
},
...
]
Array B(bData) looke like:
[
{
id: 1
prop: 3,
otherporp: `prop`
code: 'hi67'
},
...
]
In order to combine the arrays I am doing concat and reduce to get only matching id's
const data: any = aData.concat(bData).reduce((acc, x) => {
acc[x.id] = Object.assign(acc[x.id] || {}, x);
return acc;
}, {});
return Object.values(data);
But the issue is that my bData code props getting lost.
Is there any way I can rename the code from aData to say aCode and the code from bData to bCode ?

You can create a new array from both of your array with updated key value aCode and bCode instead of code key. Then concat both of these arrays and merge them on the id key.
const arrA = [{ id: 1, title: `title`, code: '34x' }],
arrB = [{ id: 1, prop: 3, otherporp: `prop`, code: 'hi67'}];
const newArrA = arrA.map(({code, ...rest}) => ({...rest, aCode : code}));
const newArrB = arrB.map(({code, ...rest}) => ({...rest, bCode : code}))
const merged = Object.values([].concat(newArrA, newArrB).reduce((r,o) => {
r[o.id] = r[o.id] || Object.assign({},o);
Object.assign(r[o.id], o);
return r;
}, {}));
console.log(merged);

var arrA = [{
id: 1,
title: `title`,
code: '34x'
}],
arrB = [{
id: 1,
prop: 3,
otherporp: `prop`,
code: 'hi67'
}];
let newArrA = arrA.map(({
code,
...rest
}) => ({ ...rest,
aCode: code
}));
const newArrB = arrB.map(({
code,
...rest
}) => ({ ...rest,
bCode: code
}));
result = newArrA.map(function(v) {
var ret;
$.each(newArrB, function(k, v2) {
if (v2.id === v.id) {
ret = $.extend({}, v2, v);
return false;
}
});
return ret;
});
console.log(result);
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>

Related

React.js: How to find duplicates for properties in an array of object and put a progressive number on that field

I have an array of object and each object is for example :
const myArr=[{name:"john",id:1}{name:"john",id:2}{name:"mary",id:3}]
for the first 2 element for the property "name" I have the name "john" that is duplicate.
How can I modify the rendered names like that:
const myArr=[{name:"john (1 of 2)",id:1}{name:"john (2 of 2)",id:2}{name:"mary",id:3}]
Thanks in advance!
Reduce the input array into a map by name (i.e. group by name property), and map the array of values to the result array. If the group array has more than 1 element in it then sub-map the group to include the numbering. Flatten the overall result.
const myArr = [
{ name: "john", id: 1 },
{ name: "john", id: 2 },
{ name: "mary", id: 3 }
];
const res = Object.values(
myArr.reduce((groups, current) => {
if (!groups[current.name]) {
groups[current.name] = [];
}
groups[current.name].push(current);
return groups;
}, {})
).flatMap((value) => {
if (value.length > 1) {
return value.map((current, i, arr) => ({
...current,
name: `${current.name} (${i + 1} of ${arr.length})`
}));
}
return value;
});
console.log(res);
You can do use reduce(), filter(), and flat() and do this:
const myArr = [
{name:"john", id:1},
{name:"john", id:2},
{name:"mary", id:3}
]
const res = Object.values(myArr.reduce((acc, curr) => {
const total = myArr.filter(({ name }) => name === curr.name).length;
if(!acc[curr.name]) {
acc[curr.name] = [
{...curr}
]
} else {
const currentSize = acc[curr.name].length;
if(currentSize === 1) {
acc[curr.name][0].name = `${acc[curr.name][0].name} (1 of ${total})`
}
acc[curr.name].push({
...curr,
name: `${curr.name} (${currentSize + 1} of ${total})`
})
}
return acc;
}, {})).flat();
console.log(res);
const myArr = [{name:"john",id:1}, {name:"john",id:2}, {name:"mary",id:3}];
const namesArray = myArr.map(elem => elem.name);
const namesTraversed = [];
let currentCountOfName = 1;
let len = 0;
myArr.forEach(elem => {
len = namesArray.filter(name => name === elem.name).length;
if (len > 1) {
if (namesTraversed.includes(elem.name)) {
namesTraversed.push(elem.name);
currentCountOfName = namesTraversed.filter(name => name === elem.name).length;
elem.name = `${elem.name} (${currentCountOfName} of ${len})`;
} else {
namesTraversed.push(elem.name);
currentCountOfName = 1;
elem.name = `${elem.name} (${currentCountOfName} of ${len})`;
}
}
});
console.log(myArr);
Check if this helps you
const myArr = [{
name: "john",
id: 1
}, {
name: "john",
id: 2
}, {
name: "mary",
id: 3
}]
// to keep a track of current copy index
let nameHash = {}
const newMyArr = myArr.map(ele => {
const noOccurence = myArr.filter(obj => obj.name ===ele.name).length;
if(noOccurence > 1){
// if there are multiple occurences get the current index. If undefined take 1 as first copy index.
let currentIndex = nameHash[ele.name] || 1;
const newObj = {
name: `${ele.name} (${currentIndex} of ${noOccurence})`,
id: ele.id
}
nameHash[ele.name] = currentIndex+ 1;
return newObj;
}
return ele;
})
console.log(newMyArr);

i can't get array b of object a with reduce in js

i can't get array b of object a with reduce in js
can you help me find the error?
const a = {
dias:"valor",
horas:"valor"
}
const b = campos.reduce((acc, el) => ([...acc, {
title: el, field: el
}]), {})
desired result = [
{ title: 'dias', field: 'dias' },
{ title: 'horas', field: 'horas' },
]
You can use Object.keys().
const a = {
dias: "valor",
horas: "valor",
};
const b = Object.keys(a).map((key) => ({ title: key, field: key }));
console.log(b);
If you want the value of the property as the field instead, you can use Object.entries():
const a = {
dias: "valor",
horas: "valor",
};
const b = Object.entries(a).map(([key, value]) => ({
title: key,
field: value,
}));
console.log(b);
As a note, the [key, value] syntax is called array destructuring.

JavaScript / ES6 -- Replace some keys in an array of objects, given key map

I have some (potentially very large) array of objects like this:
[
{
'before1' => val,
'same' => val,
'before2' => val
},
...
]
I need an efficient way to replace only some of the keys in the map (i.e. deleting keys won't work for me), and I have a map like this:
keyReplacements = {
'before1' => 'after1',
'same' => 'same',
'before2' => 'after2'
}
I know the same => same is not necessary in the map, but it's helpful to include as a full translation schema.
Given this key mapping, what's an efficient method to replace my given array of objects with the following result?
[
{
'after1' => val,
'same' => val,
'after2' => val
},
...
]
I've tried the following:
static replaceObjectKeys(objectToReplace, keyMap) {
objectToReplace.map(o =>
Object.keys(o).map((key) => ({ [keyMap[key] || key]: o[key] })
).reduce((objectToReplace, b) => Object.assign({}, objectToReplace, b)))
return objectToReplace
}
But it just returns me the same object with nothing replaced
const newObject = this.replaceObjectKeys(oldObject, keyMap)
console.log("new obj: ", newObject) // this is the same as oldObject
return newObject
Here's a solution using entries:
const arr = [
{
'before1': 1,
'same': 2,
'before2': 3
}, {
'before1': 4,
'same': 5,
}, {
'before1': 6,
'before2': 7
}, {
'same': 8,
'before2': 9
},
];
const keyReplacements = {
'before1': 'after1',
'same': 'same', // this is not necessary
'before2': 'after2'
};
const newArr = arr.map(obj =>
Object.fromEntries(Object.entries(obj).map(([k, v]) => [keyReplacements[k] || k, v]))
);
console.log(newArr);
Use ES6 map()
arrayObj = arrayObj.map(item => {
return {
value: item.key1,
key2: item.key2
};
});

How to convert object key value pair with array as values to multi objects of key value pair?

I have an object with key-value pair and its value as an array of elements.
{
status: ["new", "old"],
place: ["york", "blah"]
}
I'm trying to convert it into multiple array objects of key-value pair like below.
{
"newObj1": [
{ "status": "new" },
{ "status": "old" }],
"newObj2": [
{ "place": "york" },
{ "place": "blah" }]
}
Is there any way to achieve the above structure? I have tried couple of methods using array reduce methods but it doesn't give in the desired output.
let value= {
status: ["new", "old"],
place: ["york", "blah"]
}
Object.keys(value).map((key) => [key, value[key]]);
You can do something like this
const obj = {
status: ["new", "old"],
place: ["york", "blah"]
};
const result = {};
Object.keys(obj).forEach((key, index) => {
result[`newObj${index + 1}`] = obj[key].map(item => ({[key]: item}));
});
console.log(result);
Here's a solution that uses Array.reduce():
const value = {
status: ["new", "old"],
place: ["york", "blah"]
};
const result = Object.keys(value).reduce((acc, key, i) => {
acc["newObj" + (i + 1)] = value[key].map(k => ({ [key]: k }));
return acc;
}, {});
console.log(result);
Here is my way of accomplishing that.
let source = {
status: ["new", "old"],
place: ["york", "blah"]
};
let destination = {}; // make room for the destinoation object
Object.keys(source).forEach((key, index) => {
let obj = "newObj" + (index + 1); // assume all objects are named "newObj1,2,3,etc"
if (!destination[obj]) { // check if the object exists already
// if not, then crate an empty array first
destination[obj] = [];
}
// loop through all items in the source element array
source[key].forEach(value => {
// create an object from the array element
let subObj = {};
subObj[key] = value;
// push that object to the destination
destination[obj].push(subObj);
});
});
console.log(destination);
const data = {
status: ["new", "old"],
place: ["york", "blah"]
};
let result = Object.fromEntries( Object.entries(data).map( ([key, [first, second]], index) => {
return [ `newObj${index}`, [ { [key]: first }, { [key]: second } ] ];
} ) );
console.log(result);
Here's an idiomatic solution using .reduce inside .reduce:
Object.entries(data)
.reduce((result, [key, value], index) => !(result['newObj' + (index + 1)] = value
.reduce((arr, text) => !arr
.push({ [key]: text }) || arr, [])) || result, {});
Here's a live example:
const data = {
status: ['new', 'old'],
place: ['york', 'blah']
};
const result = Object.entries(data)
.reduce((result, [key, value], index) => !(result['newObj' + (index + 1)] = value
.reduce((arr, text) => !arr
.push({ [key]: text }) || arr, [])) || result, {});
console.log(result);
/*
{
newObj1: [
{ status: 'new' },
{ status: 'old' }
],
newObj2: [
{ place: 'york' },
{ place: 'blah' }
]
}
*/
For those who fail to understand map and reduce, here's a fairly naive solution but it will work:
newObjCounter = 1
orig = { status: [ 'new', 'old' ], place: [ 'york', 'blah' ] }
newObject = {}
//Initialise object with new keys with arrays as values
for(var key in orig){
newObject["newObj"+initialCounter] = []
initialCounter++
}
//Loop through keys of the original object and dynamically populate the new object
for(var key in orig){
index = "newObj"+objCounter
newObject[index].push({[key]:orig[key]})
objCounter++
}
console.log(newObject)

How to transform Array to Object?

What is the best way to transform an array like this:
const arr = [
{ name: 'Bob' },
{ name: 'Ben' }
{ name: 'Cole' }
{ name: 'Mary' }
{ name: 'Travis' }
]
to an object like:
const obj = {
'B': ['Bob', 'Ben'],
'C': ['Cole'],
'M': ['Mary'],
'T': ['Travis']
}
Using only vanilla JS
You can use array#reduce. Iterate through each object of your array and then extract out the first letter and add names corresponding to it.
const arr = [{name: 'Bob'}, {name: 'Ben'}, {name: 'Cole'}, {name: 'Mary'}, {name: 'Travis'}],
result = arr.reduce((r,{name}) => {
r[name[0]] = r[name[0]] || [];
r[name[0]].push(name);
return r;
},{});
console.log(result);
Vanilla JS you say? Here you go
let nil = x => x === undefined;
let empty = ([h]) => nil(h);
let first = ([h]) => h;
let last = ([h, ...t]) => empty(t) ? h : last(t);
let map = ([h, ...t], f) => nil(h) ? [] : [f(h), ...map(t, f)];
let reduce = ([h, ...t], f, i) => nil(h) ? i : reduce(t, f, f(i, h));
let tab = (a, f) => map(a, x => [x, f(x)]);
let push = (a, x) => nil(a) ? [x] : [...a, x];
let groupBy = (a, f) => _groupBy(tab(a, f));
let _groupBy = ka => reduce(ka, (g, [x, k]) => ({...g, [k]: push(g[k], x)}), {});
///
const arr = [{ name: 'Bob' },{ name: 'Ben' },{ name: 'Cole' },{ name: 'Mary' },{ name: 'Travis' }]
z = groupBy(map(arr, x => x.name), first)
console.log(z)
No built-ins!
I created an array where the key is the first letter of the name using the reduce function and restructuring the 'name' from the objects. If the key exists in the array the name is pushed (using spread operator). Else, it creates the key with only one element.
const arr = [
{ name: 'Bob' },
{ name: 'Ben' },
{ name: 'Cole' },
{ name: 'Mary' },
{ name: 'Travis' }
];
const obj = arr.reduce((res, {name})=>{
res[name[0]] = res[name[0]] ? [...res[name[0]],name] : [name];
return res;
}, {});
console.log(obj);
I think this thread is missing a non functional answer, so here it is:
const obj = {};
for(const {name} of arr)
(obj[name[0]] || (obj[name[0]] = [])).push({name});
let obj = {};
arr.forEach( e => {
const name = e.name;
if (!obj[name.charAt(0)]) obj[name.charAt(0)] = [];
obj[name.charAt(0)].push(name);
})
I'm generating a new object and adding to it news keys based in the first char of the name values (only if the key hasn't been already added).
Then, I add each value to the key that corresponds.

Categories

Resources