I want to append a new array to an existing array.
var input1 = [ { name: 'one' }, { name: 'two' }, { name: 'three' } ];
var input2 = [ { age: '1' }, { age: '2' }, { age: '3' } ];
result = [ { name: 'one', age: '1' }, { name: 'two', age: '2' }, { name: 'three', name: 'three' } ];
here is my attempt, but it is not working:
var original = "one,two,three";
var myarray = [{ age: '1' }, { age: '2' }, { age: '3' }];
// this myarray could ALSO be an empty [] array.
myarray += original.split(',').map(s => ({name: s}));
console.log(myarray)
Please help to achieve this result. thanks
(this is not a duplicate question, cuz we are dealing with possible difference in the length of one of the arrays).
If you need to handle the case where the two input arrays are different sizes, you'll have to iterate over the maximum length and output to an array a concatenation of the two input objects. Here's an example of how that could be done:
var input1 = [ { name: 'one' }, { name: 'two' }, { name: 'three' } ];
var input2 = [ { age: '1' }, { age: '2' }, { age: '3' } ];
var output = [];
var maxLength = Math.max(input1.length, input2.length);
for (var i = 0; i < maxLength; i++) {
// here we create a new object which is a combination
// of the item from both input arrays and add it to output
output.push(Object.assign({}, input1[i], input2[i]));
}
console.log(output);
The output array would be the length of the longest input array.
If you want to merge the objects at the same indexes in the two arrays and then return a new array you can do something like this:
result = input1.map((obj, index) => ({
...obj,
...input2[index]
}))
edit with working snippet:
const input1 = [ { name: 'one' }, { name: 'two' }, { name: 'three' } ];
const input2 = [ { age: '1' }, { age: '2' }, { age: '3' } ];
function mergeObjectsInArray(arr1, arr2) {
return arr1.map((obj, index) => ({
...obj,
...arr2[index]
}));
}
console.log(mergeObjectsInArray(input1, input2))
If both arrays have the same length, you can loop trough one of them, and you can use Object.assign() to merge objects. For example:
var input1 = [ { name: 'one' }, { name: 'two' }, { name: 'three' } ];
var input2 = [ { age: '1' }, { age: '2' }, { age: '3' } ];
var x = [];
for (i in input1) {
x[i] = Object.assign(input1[i], input2[i])
}
the variable x will hold the value you desire.
Related
in an arry of objects i want to remove object which have same id (duplicated data) using javascript.
below is the input array
const input = [
{
id: '1',
name: 'first',
},
{
id: '1',
name: 'first',
},
{
id: '2',
name: 'second',
},
{
id: '2',
name: 'second',
},
]
so as you see from above array there are duplicating data with id '1' and '2'.
if there is similar id i want include only one
so the expected output is like below,
const output = [
{
id: '1',
name: 'first',
},
{
id: '2',
name: 'second',
},
]
how can i do this. could someone help me with this. i am new to programming thanks.
You can use reduce to filter data from the array based on some condition like bellow
const input = [
{
id: '1',
name: 'first',
},
{
id: '1',
name: 'first',
},
{
id: '2',
name: 'second',
},
{
id: '2',
name: 'second',
},
]
const result = input.reduce((accumulator, current) => {
let exists = accumulator.find(item => {
return item.id === current.id;
});
if(!exists) {
accumulator = accumulator.concat(current);
}
return accumulator;
}, []);
console.log(result);
Similar to this answer. You will have to change the const to let while declaring input though, or use a new variable I suppose.
filtered_input = input.filter((value, index, self) =>
index === self.findIndex((t) => (
t.id === value.id
))
)
There is a lot of good approachs here.
Here is my approach for removing matching property from the original array and sending it back in the return if found.
I prefer to use this one, if you are looping through a external array and matching them, this way you dont need to loop through the whole array again and again for each, because while you are finding the matches it keeps removing them from the original array, increasing performance.
Note that this will return the first match found
let id = "601985b485d9281d64056953"
let contacts = [{
...,
parent: "601985b485d9281d64056953",
...,
},
{
...,
parent: "601985b485d9281d64065128",
...,
}
]
function findAndRemoveObjectFromArray(array, internalProperty, externalProperty, convertType = "string", returnObject = false) {
let objIndex = -1
if (convertType === "string") objIndex = array.findIndex((obj) => String(obj[`${internalProperty}`]) === String(externalProperty));
if (convertType === "number") objIndex = array.findIndex((obj) => Number(obj[`${internalProperty}`]) === Number(externalProperty));
if (objIndex > -1) {
const object = array.splice(objIndex, 1);
if (returnObject) return object.shift()
return object
}
return [];
}
let currentContact = findAndRemoveObjectFromArray(contacts, "parent", id, 'string', true)
// Results:{..., parent: "601985b485d9281d64056953",...}
you could use Set to get rid of the duplicate data like this
const input = [
{
id: '1',
name: 'first',
},
{
id: '1',
name: 'first',
},
{
id: '2',
name: 'second',
},
{
id: '2',
name: 'second',
},
]
const result = [...new Set(input.map(JSON.stringify))].map(JSON.parse)
console.log(result)
Below is another approach
const input = [
{
id: '1',
name: 'first',
},
{
id: '1',
name: 'first',
},
{
id: '2',
name: 'second',
},
{
id: '2',
name: 'second',
},
];
const uniqueIds = new Set();
const uniqueList = input.filter(element => {
const isDuplicate = uniqueIds.has(element.id);
uniqueIds.add(element.id);
return !isDuplicate;
});
console.log(uniqueList);
I wonder how I can group this array based on the prefix text in name key (split the name key at the : colon) using Lodash.
const tags = [
{ name: 'Animals: Frogs', id: 1 },
{ name: 'Animals: Lions', id: 2 },
{ name: 'Birds: Crows', id: 3 }
];
to
const tags = [{
animals: [
{ name: 'Frogs', id: 1 },
{ name: 'Lions', id: 2 },
],
birds: [
{ name: 'Crows', id: 3}
]
}];
Does Lodash have any functions to handle this, or is a custom function/regex needed?
If the pure JS suffices, it can be done this way (the result is an object here, not an array, but this can be changed if needed):
const tags = [
{ name: 'Animals: Frogs', id: 1 },
{ name: 'Animals: Lions', id: 2 },
{ name: 'Birds: Crows', id: 3 }
];
const tags2 = tags.reduce(
(acc, { name, id }) => {
let [group, type] = name.split(': ');
group = group.toLowerCase();
acc[group] ??= [];
acc[group].push({ name: type, id });
return acc;
},
{},
);
console.log(tags2);
let bigArray = [
{
Name: 'Alice',
children: [
{Name: 'AliceChild1', Country: 'country1'},
{Name: 'AliceChild2', Country: 'country2'}
]
},
{
Name: 'Bob',
children: [
{Name: 'BobChild1', Country: 'country3'},
{Name: 'BobChild2', Country: 'country4'}
]
},
{
Name: 'Sam',
children: [
{Name: 'SamChild1', Country: 'country5'},
{Name: 'SamChild2', Country: 'country6'}
]
},
]
I want to remove an object from array inside another array. Property Name is unique. For an example if BobChild2 is removed bigArray should return as
let bigArray = [
{
Name: 'Alice',
children: [
{Name: 'AliceChild1', Country: 'country1'},
{Name: 'AliceChild2', Country: 'country2'}
]
},
{
Name: 'Bob',
children: [
{Name: 'BobChild1', Country: 'country3'},
]
},
{
Name: 'Sam',
children: [
{Name: 'SamChild1', Country: 'country5'},
{Name: 'SamChild2', Country: 'country6'}
]
},
]
What is the best way to do this in JavaScript ?
Updated:
My answer
function removeChild(bigArray, childName) {
let copyBigArray = []
bigArray.forEach((item) => {
let Obj = {
Name: item.Name,
children: item.children.filter(c => c.Name !== childName)
}
copyBigArray.push(Obj)
})
return copyBigArray
}
Try this way:
let bigArray = [{
Name: 'Alice',
children: [{
Name: 'AliceChild1',
Country: 'country1'
},
{
Name: 'AliceChild2',
Country: 'country2'
}
]
},
{
Name: 'Bob',
children: [{
Name: 'BobChild1',
Country: 'country3'
},
{
Name: 'BobChild2',
Country: 'country4'
}
]
}
]
bigArray.forEach(function(o) {
o.children = o.children.filter(s => s.Name != 'BobChild2');
});
console.log(bigArray);
To support any nested depth you can do something like this:
function searchAndRemove(arr, query) {
for (var i = arr.length; i > 0; i--) {
if (query == arr[i].Name) {
arr.splice(i, 1);
}
}
if (arr.children) {
searchAndRemove(arr.children, query);
}
}
searchAndRemove(bigArray, 'BobChild2');
This will go through your array recursively until it finds all occurrences of BobChild2 and removes them.
Well the structure isn't optimal because it'll require iterating over 2 arrays, but I'd use filter() (documentation) something like this:
function deepFilter(array, name) {
return array.map(arr => {
if (!arr || !arr.children) {
return arr;
}
arr.children = arr.children.filter(c => c.Name !== name);
return arr;
})
}
Filter has to return a Boolean to know if the element should be returned or not.
Map has to return an element.
If you want to remove an element from the first Array once its children are empty, you could replace the map by a filter.
function deepFilter(array, name) {
return array.filter(arr => {
if (!arr || !arr.children || !arr.children.length) {
return false;
}
arr.children = arr.children.filter(c => c.Name !== name);
return arr && arr.children && arr.children.length;
})
}
--
Use them by doing:
const new = deepFilter(bigArray, 'SamChild1')
Here is an example how you could achieve it:
let bigArray = [
{
Name: 'Alice',
children: [
{Name: 'AliceChild1', Country: 'country1'},
{Name: 'AliceChild2', Country: 'country2'}
]
},
{
Name: 'Bob',
children: [
{Name: 'BobChild1', Country: 'country3'},
{Name: 'BobChild2', Country: 'country4'}
]
},
{
Name: 'Sam',
children: [
{Name: 'SamChild1', Country: 'country5'},
{Name: 'SamChild2', Country: 'country6'}
]
},
]
function filterName(name, data) {
return data.reduce((arr, item) => {
if (item.Name != name) {
if (item.children) item.children = filterName(name, item.children)
arr.push(item)
}
return arr
}, [])
}
console.log(filterName("BobChild2", bigArray));
A main loop for the initial values of the array
Another loop for children values
The first parameter is the array itself that wants to be filtered, for example: bigArray
The second parameter is the value for the filter, for example: BobChild2
The third parameter is the key for the filter, for example: Name
let bigArray = [{
Name: 'Alice',
children: [
{ Name: 'AliceChild1', Country: 'country1' },
{ Name: 'AliceChild2', Country: 'country2' }
]
},
{
Name: 'Bob',
children: [
{ Name: 'BobChild1', Country: 'country3' },
{ Name: 'BobChild2', Country: 'country4' }
]
},
{
Name: 'Sam',
children: [
{ Name: 'SamChild1', Country: 'country5' },
{ Name: 'SamChild2', Country: 'country6' }
]
},
];
function filterBigArray(array, value, filter) {
let result = [];
bigArray.forEach(person => {
let childs = [];
person.children.forEach(children => {
if (children[filter] !== value) {
childs.push(children);
}
});
result.push(childs);
});
return result;
}
let res = filterArray(bigArray, 'BobChild2', 'Name');
console.log(res);
You can also filter different keys, for example:
let res = filterBigArray(bigArray, 'country3', 'Country');
console.log(res);
For example
const data = [
{
companies: [
{name: 'Yuri'},
{name: 'Boeing'},
{name: 'Laser'},
],
sectors: [
{name: 'Logistic'},
{name: 'Aviation'},
{name: 'Vocal'},
],
location: [
{name: 'Hong'},
{name: 'Singapore'},
{name: 'Switzerland'},
],
},
];
if a text is searched as 'vocal' how can we search and return value in same format.
This should not be to hard.
Use reduce and filter
See example below
const data = [
{
companies: [{
name: 'Yuri'
},
{
name: 'Boeing'
},
{
name: 'Laser'
},
],
sectors: [{
name: 'Logistic'
},
{
name: 'Aviation'
},
{
name: 'Vocal'
},
],
location: [{
name: 'Hong'
},
{
name: 'Singapore'
},
{
name: 'Switzerland'
},
],
}];
var searchText = "Vocal".toLowerCase();
var result = data.reduce((arr, value) => {
var item = {}
const search=(key)=>{
item[key] = value[key].filter(x => x.name.toLowerCase().indexOf(searchText) != -1);
}
search("companies")
search("sectors")
search("location")
arr.push(item)
return arr;
}, [])
console.log(result)
I would just loop over and filter. Maybe something like this: Search a JavaScript object
It's just a loop on data array and then a loop on each item + return parent if found.
Here is one of many solutions. You have to loop over your data, and filter every entries by their key. It's important to do a .toLowerCase() Comparison.
const data = [
{
companies: [
{ name: 'Yuri' },
{ name: 'Boeing' },
{ name: 'Laser' },
],
sectors: [
{ name: 'Logistic' },
{ name: 'Aviation' },
{ name: 'Vocal' },
],
location: [
{ name: 'Hong' },
{ name: 'Singapore' },
{ name: 'Switzerland' },
],
},
];
const query = 'vocal'
let result = {}
Object.keys(data[0]).forEach(key => {
data[0][key].filter(str => {
if (str.name.toLowerCase() === query.toLowerCase()) {
result = str
}
})
})
console.log(result) // { name: 'Vocal'}
You can use a for-in loop to go through the object keys, and a for-of to go through the array of objects:
const data = [
{
companies: [
{name: 'Yuri'},
{name: 'Boeing'},
{name: 'Laser'},
],
sectors: [
{name: 'Logistic'},
{name: 'Aviation'},
{name: 'Vocal'},
],
location: [
{name: 'Hong'},
{name: 'Singapore'},
{name: 'Switzerland'},
],
},
];
function search() {
let searchVal = document.getElementById('search').value.toLowerCase().trim();
for (let key in data[0]) {
for(obj of data[0][key]) {
if(searchVal == obj.name.toLowerCase()) {
console.log(obj);
return;
}
}
}
console.log("Item was not found.");
}
<input type="text" id="search" value="" />
<input type="button" value="Search" onclick="search()" />
It is not clear to me exactly what you want to be returned, but here is one way to search, within an object, for an object containing a particular case-insensitive string value, not matter how deeply the object is nested.
const search = (object, string) => {
for (const value of Object.values(object)) {
if (typeof value === 'object') {
const result = search(value, string);
if (result !== undefined) return result;
} else if (typeof value === 'string') {
if (value.toLowerCase() === string.toLowerCase()) return object;
}
}
};
search(data, 'vocal'); // { name: "Vocal" }
I have 2 arrays:
blockedNumbers: ['123', '456', '789', '247'];
contacts: [
{name: 'Foo', numbers: [{ home:'123' }, { mobile:'456' }]},
{name: 'Bar', numbers: [{ home:'789' }]}
]
I want to create a new array of blocked contacts which will contain:
[
{ name: Foo, numbers: [{ home:'123' }, { mobile:'456' }] },
{name: 'Bar', numbers: [{ home:'789' }]}
'247'
]
So the solution I have tried first loops over blocked numbers, then forEach contact, if blocked number in numbers, push to array. But the result turns out as
[
'123'
{ name: Foo, numbers: ['123', '456'] },
{name: 'Bar', numbers: ['789']}
'456'
'789'
'247'
]
Code below:
const newBlacklistWithContacts = [];
blockedNumbers.forEach((blockedNumber) => {
contacts.map((contact) => {
// if blocked number in contacts
Object.keys(contact.numbers).forEach((e) => {
if (contact.numbers[e] === blockedNumber) {
const alreadyAdded = newBlacklistWithContacts.find(blacklistContact => blacklistContact.name === contact.name);
if (!alreadyAdded) {
return newBlacklistWithContacts.push({ name: contact.name, numbers: contact.numbers });
}
}
else if (!newBlacklistWithContacts.includes(blockedNumber)) {
return newBlacklistWithContacts.push(blockedNumber);
}
});
});
});
I'm sure there is a more efficient way to do this & actually return what I need? (All of the blacklisted contacts and if not in contacts, only the number) I am using js and React.js in this project
If your data set is really large, you can optimise your algorithm by doing O(1) lookups in a Set instead of using indexOf or includes which do O(n) lookups:
// Input
const blockedNumbers = ['123', '456', '789', '247'];
const contacts = [{name: 'Foo', numbers: [{ home:'123' }, { mobile:'456' }]}, {name: 'Bar', numbers: [{ home:'789' }]}];
// Algorithm
const set = new Set(blockedNumbers);
const notused = new Set(blockedNumbers);
const newBlacklistWithContacts = contacts.filter(contact =>
contact.numbers.map(obj => Object.values(obj)[0])
.filter(number => set.has(number) && (notused.delete(number) || true)).length
).concat(...notused);
// Output
console.log(newBlacklistWithContacts);
.as-console-wrapper { max-height: 100% !important; top: 0; }
var blockedNumbers = ['123', '456', '789', '247'];
var contacts = [{
name: 'Foo',
numbers: [{
home: '123'
}, {
mobile: '456'
}]
},
{
name: 'Bar',
numbers: [{
home: '789'
}]
}
]
var blocks = [];
contacts.forEach(v1 => (v1.numbers.forEach(v2 => {
blocks.push(Object.values(v2)[0]);
})));
blockedNumbers.forEach(val => (blocks.indexOf(val) == -1 ? contacts.push(val) : null));
console.log(contacts);