Split each element in array into object after certain character - javascript

I'm new to node.js and javascript. I have the following array:
var oldarray = [
'name1\tstreet\tperson\tphone1\tphone2\nname2\street2\tperson1\tphone82\tphone3\n'
]
Note, this is a single element array. First, I require the array to contain a new element after each new line first, then, re-format like below:
let headers = {
name: "",
street: "",
person: "",
phone 1 "",
phone 2 ""
}
How can I parse through each element (after creating a new element after each +), and assign an object within an array after each instance of \
The desired output is this:
[{
name: 'name1',
street: 'street2',
person: 'person1',
phone1: 'phone82 ',
phone2: 'phone3'
},
{
name: 'name2',
street: 'street2',
person: 'person1',
phone1: 'phone1 ',
phone2: 'phone2'
}]
Any help is highly appreciated.

If you have the same structure for all items in OLD_ARRAY you can use map, filter and reduce in order to manipulate your input.
So what I did?
In case that you have multiple strings like the example input (more than 1 array item) I convert it to sub-arrays of each string by using map and split by \n, which is your string separator. Than I filtered it by strings that are not empty (becasue that you have a post-fix of \n as well).
From each sub-array I extracted all the contacts using extractContacts function - it splites the sub-array by your separaotr, \t, and map it according to your contacts temaplte.
Since it's a format of array of arrays, I used reduce to concat all the arrays together
const OLD_ARRAY = [
'name1\tstreet\tperson\tphone1\tphone2\n' +
'name2\tstreet2\tperson1\tphone82\tphone3\n'
];
function extractContacts(templates) {
return templates.map(t => t.split('\t'))
.map(details => ({
name: details[0],
street: details[1],
person: details[2],
phone1: details[3],
phone2: details[4]
}));
}
let contacts = OLD_ARRAY.map(str => str.split('\n').filter(str => str !== ''))
.map(template => extractContacts(template))
.reduce((a, acc) => acc.concat(a), []);
console.log(contacts)

You can split each oldarray value on \n and then \t into newarray, and then use Object.fromEntries to build an object from each newarray value, combining the split values with each key from headers:
var oldarray = [
'name1\tstreet\tperson\tphone1\tphone2\n' +
'name2\tstreet2\tperson1\tphone82\tphone3\n'
]
let newarray = [];
oldarray.forEach(s => s.trim().split('\n').map(v => newarray.push(v.split('\t'))));
let headers = {
'name': "",
'street': "",
'person': "",
'phone 1': "",
'phone 2': ""
}
let keys = Object.keys(headers);
out = newarray.map(s => Object.fromEntries(s.map((v, i) => [keys[i], v])));
console.log(out);

First split the array by \n to get individual paths and then split them by \t, and use reduce to create new header objects from each subarray
var oldarray = [
'name1\tstreet\tperson\tphone1\tphone2\n' +
'name2\tstreet2\tperson1\tphone82\tphone3\n' +
'name4\tstreet4\tperson4\tphone84\tphone4\n'
]
arr = oldarray.flatMap(o => o.split("\n"))
c = arr.map(o => o.split("\t"))
c.pop()
result = c.reduce((acc,[name, street, person, phone1, phone2],i) => {
acc = [...acc,{name:name,street:street,person:person,phone1:phone1,phone2:phone2}]
return acc
},[])
console.log(result)

Related

I have array with objects, I need to fetch all the objects that matches the value of userId starts with 'US' [duplicate]

This question already has answers here:
How to filter object array based on attributes?
(21 answers)
Closed last year.
Below is the array with objects:
myArray:[
{"name":"Ram", "email":"ram#gmail.com", "userId":"HB000006"},
{"name":"Shyam", "email":"shyam23#gmail.com", "userId":"US000026"},
{"name":"John", "email":"john#gmail.com", "userId":"HB000011"},
{"name":"Bob", "email":"bob32#gmail.com", "userId":"US000106"}
]}
I tried this but I am not getting output:
item= myArray.filter(element => element.includes("US"));
I am new to Angular.
let filteredArray = myArray.filter(function (item){
return item.userId.substring(0,2).includes('US')
})
Console.log(filteredArray)
//Output
[ { name: 'Shyam', email: 'shyam23#gmail.com', userId: 'US000026' },
{ name: 'Bob', email: 'bob32#gmail.com', userId: 'US000106' } ]
As noted by #halfer - You need to filter on the property that you are interested in - in this case - 'userId' - you can do this by simply adding the property into the code you already had tried and it will log out the specified items - or alternatively - you can make a utility function that takes the array, property and target string as arguments and this will allo2w you to search / filter other arrays and by any property and target string .
These two options are shown below and both log out the same results.
const myArray = [
{"name":"Ram", "email":"ram#gmail.com", "userId":"HB000006"},
{"name":"Shyam", "email":"shyam23#gmail.com", "userId":"US000026"},
{"name":"John", "email":"john#gmail.com", "userId":"HB000011"},
{"name":"Bob", "email":"bob32#gmail.com", "userId":"US000106"}
]
// option 1 - direct filtering
const matchingItems = myArray.filter(element => element.userId.includes("US"));
console.log(matchingItems);
// gives - [ { name: 'Shyam', email: 'shyam23#gmail.com', userId: 'US000026' }, { name: 'Bob', email: 'bob32#gmail.com', userId: 'US000106' } ]
//option 2 - create a function that takes arguments and returns the matches
const matches = (arr, prop, str) => {
return arr.filter(element => element[prop].includes(str));
}
console.log(matches(myArray, 'userId', 'US'));
// gives - [ { name: 'Shyam', email: 'shyam23#gmail.com', userId: 'US000026' }, { name: 'Bob', email: 'bob32#gmail.com', userId: 'US000106' } ]

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);

Javascript, filtering array of objects and return all the unique objects

I have an array of objects, that contains properties that are objects:
let allPersons = [
{ id: "abcdefg",
name: "tom",
...
phone: {
brand: "blah"
id: "hijklm"
...
}
},
{ id: ....}, {...}, {...}
];
What I need to do is filter those objects and returning all the phones, filtering them by id so all phones returned are unique.
I tried to retrieve first all the phones:
// allPersons is the full array mentioned above
let phones = [...new Set(allPersons.map(person => person.phone))];
then I tried to return all the unique phones, but unsuccessfully:
let result = phones.map(phone => phone.id).filter((value, index, self) => self.indexOf(value) === index)
This returns only the unique ids of the phones, but I want the entire object. What can I do?
UPDATE:
phone Ids are NOT unique, e.g. nokia3310 has id 1, nokia3330 has id 2, etc: so tom and john can have the same phone and phone ids could be duplicated!
Make an object indexed by IDs instead, then take the object's values:
const phonesById = Object.fromEntries(
allPersons.map(
({ phone }) => [phone.id, phone]
)
);
const uniquePhones = Object.values(phonesById);
If you're trying to get the phone object in each object of the array, then the code below will do that for you.
It gets the phone object and stores it in a
var objArr = [
{id: "abcdefg", name: "tom", phone: {brand: "blah", id: "hijklm"}},
{id: "guidiuqwbd", name: "john", phone: {brand: "hihihih", id: "ayfva"}},
{id: "yuygeve", name: "doe", phone: {brand: "hahahah", id: "cqcqw"}}
]
var allPhoneObjects = [];
objArr.forEach(function(currObj){
var phoneObj = currObj.phone;
allPhoneObjects.push(phoneObj);
});
console.log(allPhoneObjects);
I propose you the following solution
let uniques = new Set();
const phones = allPersons.filter(({phone}) => (
uniques.has(phone.id) ? false : !!uniques.add(phone.id)
)).map(p => p.phone)
Basically, we define a Set to record ids of the phones already processed, and a filter function on the allPersons array, that returns only the phones not already in the Set. We complete with the map to extract only the portion of JSON needed
EDIT
You can use just one function on the allPersons array using the reduce function
let uniques = new Set();
const phones = allPersons.reduce( (filtered, {phone}) => {
if (!uniques.has(phone.id)) {
filtered.push(phone);
uniques.add(phone.id);
}
return filtered
}, [])

How to transform a nested array into string if it contains null values or just an empty one?

I need to replace nested arrays inside a main array that have null values like lets say [null, null] or the nested arrays that are empty with a string value like "empty".
Saying that we have the following array:
array = [
{
id: 123,
name: 'Peter',
phone: [null, null],
addresses: [{ address1: 'Manchester, UK', address2: 'London, UK' }]
},
{
id: 124,
name: 'Sara',
phone: [],
addresses: [{ address1: 'London, UK', address2: 'Paris, FR' }]
}
];
We see that, the first array has phone: [null, null] and the second has it as []. What I need to do it to transform them into the following:
array = [
{
id: 123,
name: 'Peter',
phone: "empty",
addresses: [{ address1: 'Manchester, UK', address2: 'London, UK' }]
},
{
id: 124,
name: 'Sara',
phone: "empty",
addresses: [{ address1: 'London, UK', address2: 'Paris, FR' }]
}
];
This is an example, and each array might contain multiple nested arrays that have the same [null, null] or [].
I tried the following:
var filtered = this.array.map(subarray => subarray.filter(el => el != null));
from this Stack Overflow answer, but I've got an error saying:
Error: subarray.filter is not a function
Then I tried a second method using lodash's every() and isNull method and property but couldn't figure it out:
let props = [];
props = Array.from(new Set(this.array.flatMap(e => Object.keys(e), [])));
console.log(props)
for (const prop of props) {
this.array.forEach(e => {
if ((Array.isArray(e[prop]) || typeof(e[prop]) === 'object') && e[prop]._.every(_.isNull)) {
console.log(e)
}
});
}
I searched few questions on Stack Overflow but the structure of the arrays are like: [ [1, 2], [1,3]...] and not like my array's structure [{...}, {...}], so I tried some of the solution and got the same error of method 1 above.
Here is a stackblitz.
First loop through the array, and within each object, you can set the phone property:
for(const entry of array) {
const isEmpty = entry.phone.filter(p => p !== null).length === 0;
entry.phone = isEmpty ? 'empty' : entry.phone;
}
Caveat is that this edits your array. One concern about the premise of the question is that you are setting an array property to a string, which is not ideal.
Live Example: https://jsfiddle.net/michaschwab/9ze3p2or/3/, and here's your edited stackblitz: https://stackblitz.com/edit/null-nested-array-into-string-jwhfwn
If you want to not modify your array, this is a way to do it:
const modified = array.map(entry => {
return {...entry, // Copy previous values
phone: entry.phone.filter(p => p !== null).length === 0 ? 'empty' : entry.phone
};
});
Map the array, and use _.mapValues() on each object. For each values that is an array, and full of null values, return 'empty':
const array = [{"id":123,"name":"Peter","phone":[null,null],"addresses":[{"address1":"Manchester, UK","address2":"London, UK"}]},{"id":124,"name":"Sara","phone":[],"addresses":[{"address1":"London, UK","address2":"Paris, FR"}]}];
const result = array.map(o =>
_.mapValues(o, v => // map the values of the object
_.isArray(v) && v.every(_.isNull) ? 'empty' : v // if a value is an array, and all values are null return 'empty'
)
);
console.log(result);
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.15/lodash.js"></script>

How to merge two arrays in JavaScript and remove the duplicate items?

I have two arrays
var array1 = [{firstName:'John', age:32, email:'xyz1#email.com'}, {firstName:'Jack', age:40, email:'xyz2#email.com'}];
var array2 = [{firstName:'Jen', age:29, email:'abc1#email.com'}, {firstName:'Jack', age:40, email:'xyz2#email.com'}];
I would like to merge the two arrays and get the below output
var array3 = [{firstName:'John', age:32, email:'xyz1#email.com'}, {firstName:'Jack', age:40, email:'xyz2#email.com'}, {firstName: 'Jen', age: 29, email: 'abc1#email.com'}];
Would like to know best way to merge two arrays in JavaScript so that I get only the unique items from each array?
Answer
You can do this using Rest Operators, the Set Object and JSON methods:
[ ...new Set([...a1, ...a2].map(JSON.stringify)) ].map(JSON.parse);
Example
var array1 = [{firstName:'John', age:32, email:'xyz1#email.com'}, {firstName:'Jack', age:40, email:'xyz2#email.com'}];
var array2 = [{firstName:'Jen', age:29, email:'abc1#email.com'}, {firstName:'Jack', age:40, email:'xyz2#email.com'}];
function joinArrays(a1, a2) {
return [ ...new Set([...a1, ...a2].map(JSON.stringify)) ].map(JSON.parse);
}
console.log(joinArrays(array1, array2));
Explanation:
You combine Arrays by using Rest Operators:
[...a1, ...a2]
You turn the Objects into Strings with JSON.stringify:
[...a1, ...a2].map(JSON.stringify)
You place these Strings into a Set. Sets do not allow duplicate Primitive Values( strings, numbers, etc )
new Set([...a1, ...a2].map(JSON.stringify))
You use the Rest Operator to place the Set into an Array
[...new Set([...a1, ...a2].map(JSON.stringify))]
You map the Array using JSON.parse to turn the strings back into Objects, minus duplicates.
[ ...new Set([...a1, ...a2].map(JSON.stringify)) ].map(JSON.parse);
You can use the reduce method to merge without duplicates and ensure the mapping is efficient in-case the arrays are long
First you create a map of the elements in the first array with the key firstName. This will save on performance for large arrays/lists
const array1Map = array1.reduce(
(state, payload) => ({...state, [payload.firstName]: payload})
)
Then you create a new array by merging the two arrays but check against array1Map for duplicates using the reduce function again
const mergedArray = array2.reduce((state, payload) => {
if (!array1Map[payload.firstName]) {
return [...state, payload]
}
return state
}, array1)
The new array is a combination of the 2 arrays without duplicates
var array1 = [{
firstName: 'John',
age: 32,
email: 'xyz1#email.com',
},
{
firstName: 'Jack',
age: 40,
email: 'xyz2#email.com',
}
]
var array2 = [{
firstName: 'Jen',
age: 29,
email: 'abc1#email.com',
},
{
firstName: 'Jack',
age: 40,
email: 'xyz2#email.com',
}
]
const array1Map = array1.reduce(
(state, payload) => ({ ...state,
[payload.firstName]: payload
})
)
const mergedArray = array2.reduce((state, payload) => {
if (!array1Map[payload.firstName]) {
return [...state, payload]
}
return state
}, array1)
console.log(mergedArray)

Categories