Nested iteration over collection - javascript

I am trying to assemble a string using output from two collections. To do that, I iterate over one of them, using _forEach function, and use it's output as an input for another iterator. But I can't make it work.
Code:
const data1 = [{
label: 'Id',
data: 'id'
},
{
label: 'First name',
data: 'first_name'
},
{
label: 'Last name',
data: 'last_name'
},
{
label: 'IP Address',
data: 'ip_address'
},
];
const data2 = [{
"id": 1,
"first_name": "Robinet",
"last_name": "Golsby",
"ip_address": "201.83.127.236"
}, {
"id": 2,
"first_name": "Kirby",
"last_name": "Feaver",
"ip_address": "143.188.49.149"
}]
let keys = '';
const getKeys = _.forEach(data1, value => keys += '' +value.data);
let stringValue = '';
const getStringValue = _.forEach(tableData, value => stringValue += ' ' + value.first_name);
So I can get a list of keys from the first object, and I can get the list of values from the second, but only if the key is hardcoded. What I want to do is to iterate over each of the entries in data2 in the 'outer' iterator, while providing keys to get the values using iteration over data1. How do I do that?
Edit: the end result would look like:
1 Robinet Golsby 201.83.127.236

seems like:
const result = _.chain(data1)
.map('data') // get keys from data1
.thru(keys => _.map(data2, item => _.at(item, keys))) // iterate data2 and get values by keys
.map(values => _.join(values, ' ')) // values array to string
.value();
result:
["1 Robinet Golsby 201.83.127.236", "2 Kirby Feaver 143.188.49.149"]

I'm not sure if this is exactly what you want, but I think that you can achieve your goal using nesting Array#map calls:
const data1 = [{"label":"Id","data":"id"},{"label":"First name","data":"first_name"},{"label":"Last name","data":"last_name"},{"label":"IP Address","data":"ip_address"}];
const data2 = [{"id":1,"first_name":"Robinet","last_name":"Golsby","ip_address":"201.83.127.236"},{"id":2,"first_name":"Kirby","last_name":"Feaver","ip_address":"143.188.49.149"}];
const result = data2.map((obj) => data1.map(({ label, data }) => ({
label,
data: obj[data]
})));
console.log(result);

Related

How to add special character in array map?

How to add special characters like : to array map ? I want to achieve this.
'10': ["11/21/2022", "11/25/2022"]
this is what I have so far
const data = [{
"user_id": "10",
"dates": ["11/21/2022", "11/25/2022"]
}]
const output = data.map(({
user_id,
dates
}) => [user_id, dates]);
console.log(output);
I'm going to guess that you're looking for an array like this as your result:
[
{
10: ["11/21/2022", "11/25/2022"]
},
// ...possibly others here...
]
If so, return a non-array object from your map call rather than an array:
const output = data.map(({ user_id, dates }) => ({[user_id]: dates}));
// −−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−^^^^^^^^^^^^^^^^^^
Example:
const data = [
{
user_id: "10",
dates: ["11/21/2022", "11/25/2022"],
},
];
const output = data.map(({ user_id, dates }) => ({[user_id]: dates}));
console.log(output);
Note how that uses computed property name syntax to create the property in the object, [user_id]: dates. That creates a property using the value of user_id as the name.
If you just want to console.log to appear in the way you described, this then you just have to access the elements from the array and print them in the way you want.
const data = [{
"user_id": "10",
"dates": ["11/21/2022", "11/25/2022"]
}]
const output = data.map(({
user_id,
dates
}) => [user_id, dates]);
console.log(`'${output[0][0]}': ["${output[0][1][0]}, ${output[0][1][1]}"]`);

Map array return key in a string format in JavaScript

I have a function that map and create a new array from a given array. After I map the array to have a key: "value", but the map function return me the "key": "value".
How can I get or map the key not in a string format ?
let categories_name = [{ name: "test", prov_id: "f34f43"}, { name : "test1", prov_id: "233edd3"}]
.map(v => v.prov_id)
.filter((item, index, arr) => arr.indexOf(item) === index);
the result is this
["f34f43","233edd3"]
now I want to add a key (name) for each value and convert in a object
let newArray = categories_name.map(value => ({name: value}));
this is the result :
[ { "name": "f34f43" }, { "name": "233edd3" }]
but I need like that, with key not like a string.
[ { name: "f34f43" }, { name: "233edd3" }]
In a JavaScript object, all keys are strings. So the followings are exactly the same/identical:
{ "key": "value" }
{ key: "value" }
// Hence your example is identical as well:
{ "name": "f34f43" }
{ name: "f34f43" }
When you run the code below, you will see that even your original input has object properties in the form "key": "value" when printed:
let categories_name = [{ name: "test", prov_id: "f34f43"},{ name : "test1", prov_id: "233edd3"}]
console.log('source:', categories_name)
let ids = categories_name.map(v => v.prov_id)
.filter((item, index, arr) => arr.indexOf(item) === index);
console.log('ids:', ids)
let newArray = categories_name.map(value => ({name: value}));
console.log('newArray:', newArray)
That's just the standard JSON representation, what you get if you used JSON.stringify.
If you really really need the string representation to look like ES5 syntax, see my answer to the above linked SO question. Per that answer, below I use JSON5.stringify from the JSON5 library, which has a compatible interface to the built-in JSON object:
// if node, import 'json5' here, as opposed to
// the HTML script tag this example relies on
let categories_name = [{ name: "test", prov_id: "f34f43"},{ name : "test1", prov_id: "233edd3"}]
console.log('source:', JSON5.stringify(categories_name))
let ids = categories_name.map(v => v.prov_id)
.filter((item, index, arr) => arr.indexOf(item) === index);
console.log('ids:', JSON5.stringify(ids))
let newArray = categories_name.map(value => ({name: value}));
console.log('newArray:', JSON5.stringify(newArray))
<script src="https://unpkg.com/json5#^2.0.0/dist/index.min.js"></script>

how to get id based on value of objects and set into another object - javascript

There are two array of objects and i want to filter two values by iterating differently to get two different id.
Here is the example
1st array : list_of_products: [ { text: "Shoes", value: 1},{text:"Clothing", value: 2},{text:"Foods", value: 3}]
2nd Array: list_of_names: [{ text: "jim" , value: 1},{text:"Sim", value: 2},{text:"Tim",value:3}]
Now, i want to get the ids by filtering out two arrays based on names like this
product_name: "Clothing", person_name:"Tim"
Then i want to store the ids like this
const newIds = { product_id: 2,name_id: 3}
This i have tried:
const newProduct_name = list_of_products.find(name => name.text === product_name);
const newName = list_of_names.find(name => name.text === person_name);
storing it into new object like this
const values = {product_id: newProduct_name.value ,name_id: newName.value}
How to do this by minimal use of variables and faster execution?
Creating Maps or objects using the lookup values as keys lets you iterate each of your source arrays once and then have o(1) searches rather than using find() to iterate each array many times
const products= [ { text: "Shoes", value: 1},{text:"Clothing", value: 2},{text:"Foods", value: 3}],
names= [{ text: "jim" , value: 1},{text:"Sim", value: 2},{text:"Tim",value:3}];
const createMap = (arr) => new Map(arr.map(o => [o.text, o.value])),
prodMap = createMap(products),
namesMap = createMap(names);
const data = [{
product_name: "Clothing",
person_name: "Tim"
}];
const res = data.map(o => {
return {
product_id: prodMap.get(o.product_name),
name_id: namesMap.get(o.person_name)
};
})
console.log(res)

Logic to Transform data

I have an api that return me data in following format:
[
{
"_id": 1567362600000,
"KIDate": "2019-09-02",
"KITools": [
{
"data": 1,
"tool": "A"
},
{
"data": 2,
"tool": "B"
}
]
},
{
"_id": 1567519839316,
"KIDate": "2019-09-01",
"KITools": [
{
"data": 2,
"tool": "A"
},
{
"data": 1,
"tool": "C"
}
]
},
{
"_id": 1567519839317,
"KIDate": "2019-08-31",
"KITools": [
{
"data": 0,
"tool": "C"
}
]
},
]
I want to transform this data to get the following arrays:
Result 1 - [“2019-09-02”,”2019-09-01”,”2019-08-31”]
Result 2 - [ {name: ‘A’, data:[1, 2, 0] }, { name: 'B', data: [2, 0, 0] }, { name: 'C', data: [0, 1, 0]}]
Currently I am able to achieve this by using loops and per-defining variables with the tool name like following and looping the api data to push into this variable.
var result2 = [{
name: 'A',
data: []
}, {
name: 'B',
data: []
}, {
name: 'C',
data: []
}];
But this is not the expected behavior, the tool names can change and I have to figure that out dynamically based on the data returned by the api.
What is the best way to achieve this without looping like crazy.
You could use reduce method to get the result with array of dates and object of values for each tool.
const data = [{"_id":1567362600000,"KIDate":"2019-09-02","KITools":[{"data":1,"tool":"A"},{"data":2,"tool":"B"}]},{"_id":1567519839316,"KIDate":"2019-09-01","KITools":[{"data":2,"tool":"A"},{"data":1,"tool":"C"}]},{"_id":1567519839317,"KIDate":"2019-08-31","KITools":[{"data":0,"tool":"C"}]}]
const result = data.reduce((r, {KIDate, KITools}, i) => {
r.dates.push(KIDate);
KITools.forEach(({data: dt, tool}) => {
if(!r.values[tool]) r.values[tool] = Array(data.length).fill(0);
r.values[tool][i] = dt
})
return r;
}, {dates: [], values: {}})
console.log(result)
You can use reduce and forEach with Set and Map
Initialize accumulator as object with dates and data key, dates is a Set and data is Map
For every element add the KIDate to dates key,
Loop over KITools, check if that particular too exists in data Map if it exists update it's value by adding current values to id, if not set it's value as per current values
let data = [{"_id": 1567362600000,"KIDate": "2019-09-02","KITools": [{"data": 1,"tool": "A"},{"data": 2,"tool": "B"}]},{"_id": 1567519839316,"KIDate": "2019-09-01","KITools": [{"data": 2,"tool": "A"},{"data": 1,"tool": "C"}]},{"_id": 1567519839317,"KIDate": "2019-08-31","KITools": [{"data": 0,"tool": "C"}]},]
let final = data.reduce((op,{KIDate,KITools})=>{
op.dates.add(KIDate)
KITools.forEach(({data,tool})=>{
if(op.data.has(data)){
op.data.get(data).data.push(tool)
} else{
op.data.set(data, {name: data, data:[tool]})
}
})
return op
},{dates:new Set(),data: new Map()})
console.log([...final.dates.values()])
console.log([...final.data.values()])
The result1 array can be obtained via a direct .map(). To build the result2 array will require additional work - one approach would be to do so via .reduce() as detailed below:
const data=[{"_id":1567362600000,"KIDate":"2019-09-02","KITools":[{"data":1,"tool":"A"},{"data":2,"tool":"B"}]},{"_id":1567519839316,"KIDate":"2019-09-01","KITools":[{"data":2,"tool":"A"},{"data":1,"tool":"C"}]},{"_id":1567519839317,"KIDate":"2019-08-31","KITools":[{"data":0,"tool":"C"}]}];
const result1 = data.map(item => item.KIDate);
const result2 = data.reduce((result, item) => {
item.KITools.forEach(kitool => {
/* For current item, search for matching tool on name/tool fields */
let foundTool = result.find(i => i.name === kitool.tool);
if (foundTool) {
/* Add data to data sub array if match found */
foundTool.data.push(kitool.data);
} else {
/* Add new tool if no match found and init name and data array */
result.push({
name: kitool.tool,
data: [kitool.data]
});
}
});
return result;
}, []).map((item, i, arr) => {
/* Second phase of processing here to pad the data arrays with 0 values
if needed */
for (let i = item.data.length; i < arr.length; i++) {
item.data.push(0);
}
return item;
});
console.log('result1:', result1);
console.log('result2:', result2);

Mapping the array element with other array

I have two arrays
array1 = [{id:"1",title:"Writing"},{id:"2",title:"Singing"},{id:"3",title:"Dance"}];
array2 = [{tags: "1",title: "USA",type: "text"},
{tags: "1,2,3",title: "Japan",type: "image"},
{tags: "2,3",title: "Japan",type: "image"}];
I have to map the id of the array1 to tags of the array2 and display the corresponding title from the array1.
The new array2 should look like,
array2=[{tags:"Writing",title:"USA", type:"text"},
{tags: "Writing,Singing,Dance",title: "Japan",type: "image"},
{tags: "Singing,Dance",title: "Japan",type: "image"}];
I did this to get the array1 mapping and got stuck after that.
var newtags= (array1).map(obj=>{
var rObj={};
rObj[obj.id]=obj.title;
return rObj;
});
You can create a mapping object with each id as key and title as value using reduce. Then map over array2 and split each tags to get the new tags
const array1=[{id:"1",title:"Writing"},{id:"2",title:"Singing"},{id:"3",title:"Dance"}],
array2=[{tags:"1",title:"USA",type:"text"},{tags:"1,2,3",title:"Japan",type:"image"},{tags:"2,3",title:"Japan",type:"image"}]
const map = array1.reduce((r, { id, title }) => ({ ...r, [id]: title }), {});
const output = array2.map(({ tags, ...rest }) => {
const newTags = tags.split(',').map(id => map[id]).join(',')
return { tags: newTags, ...rest }
})
console.log(output)
You could also get the mapping object using Object.fromEntries()
const map = Object.fromEntries(array1.map(({ id, title }) => [id, title]));
Then use the regex /\d+(?=,|$)/ to match the numbers and replace them with their respective titles
const array1=[{id:"1",title:"Writing"},{id:"2",title:"Singing"},{id:"3",title:"Dance"}],
array2=[{tags:"1",title:"USA",type:"text"},{tags:"1,2,3",title:"Japan",type:"image"},{tags:"2,3",title:"Japan",type:"image"}]
const map = Object.fromEntries(array1.map(({ id, title }) => [id, title]));
const output = array2.map(({ tags, ...rest }) => {
const newTags = tags.replace(/\d+(?=,|$)/g, n => map[n])
return { tags: newTags, ...rest }
})
console.log(output)
Here's a solution
I'm using .map, .reduce and .replace to join array1 and array2 together.
const array1 = [
{
id: "1",
title: "Writing"
},
{
id: "2",
title: "Singing"
},
{
id: "3",
title: "Dance"
}
]
const array2 = [
{
tags: "1",
title: "USA",
type: "text"
},
{
tags: "1,2,3",
title: "Japan",
type: "image"
},
{
tags: "2,3",
title: "Japan",
type: "image"
}
]
const array3 =
array2.map(item => ({
...item,
tags: array1.reduce((tags, {id, title}) => tags.replace(id, title), item.tags),
}))
console.log(array3)
You can use filter, map and join method, split tags and filter tags in array1 first.
var newtags= (array2).map(obj=>{
let tags = obj.tags.split(",");
let titles = array1.filter(c=>tags.includes(c.id)).map(c=>c.title);
obj.tags = titles.join();
return obj;
});
array1 = [{id:"1",title:"Writing"},{id:"2",title:"Singing"},{id:"3",title:"Dance"}];
array2 = [{tags: "1",title: "USA",type: "text"},
{tags: "1,2,3",title: "Japan",type: "image"},
{tags: "2,3",title: "Japan",type: "image"}];
var newtags= (array2).map(obj=>{
let tags = obj.tags.split(",");
let titles = array1.filter(c=>tags.includes(c.id)).map(c=>c.title);
obj.tags = titles.join();
return obj;
});
console.log(newtags);
You can try following
Use Array.reduce to convert array1 into an object with id as key and title as value (Step 1)
Iterate over array2 using Array.forEach to update its tags property
To update tags property first split it by , to convert into an array
Map each value in array to its corresponding value in Object created in step 1
Join back the array with , and assign back to tags
let array1 = [{id:"1",title:"Writing"},{id:"2",title:"Singing"},{id:"3",title:"Dance"}];
let array2 = [{tags: "1",title: "USA",type: "text"},{tags: "1,2,3",title: "Japan",type: "image"},{tags: "2,3",title: "Japan",type: "image"}];
let obj = array1.reduce((a,c) => Object.assign(a, {[c.id] : c.title}), {});
array2.forEach(o => o.tags = o.tags.split(",").map(v => obj[v]).join(","));
console.log(array2);
To achieve expected result, use below option of looping array1 and replacing array2 tags with title
Loop Array1 using forEach
Replace array2 tags with each array1 title using array id
array1 = [{id:"1",title:"Writing"},{id:"2",title:"Singing"},{id:"3",title:"Dance"}];
array2 = [{tags: "1",title: "USA",type: "text"},
{tags: "1,2,3",title: "Japan",type: "image"},
{tags: "2,3",title: "Japan",type: "image"}];
array1.forEach(v =>{
const re = new RegExp(v.id, "g");
array2 = JSON.parse(JSON.stringify(array2).replace(re, v.title))
})
console.log(array2);
I would consider breaking this down into several reusable functions. Of course it might be premature abstraction, but I've seen variants of this questions like often enough here that it makes sense to me to look toward the fundamentals.
We want to be able to look up the values in a list stored as an array with what might be arbitrary field names. So we use a function makeDictionary that takes both the field names and the array and returns an object that maps them, such as {'1': 'Writing', '2': 'Singing',...}`.
Then we can use fillField supplying a dictionary, a field name, and an object, and replace that field with the result of looking up the tags in the dictionary. This is a little more specific to the problem, mostly because the comma-separated string format for your tags is a little more cumbersome than it might be if it were an array.
With these, useTags is simple to write, and it is the first function here focused directly on your needs. It combines the above, supplying the field names id and title for the dictionary and tags for your main objects.
This is what it looks like combined:
const makeDictionary = (keyName, valName) => (arr) =>
arr .reduce
( (a, {[keyName]: k, [valName]: v}) => ({...a, [k]: v})
, {}
)
const fillField = (field, dict) => ({[field]: f, ...rest}) => ({
...rest,
[field]: f .split (/,\s*/) .map (t => dict[t]) .join (', ')
})
const useTags = (tags, dict = makeDictionary ('id', 'title') (tags) ) =>
(objs) => objs .map ( fillField ('tags', dict) )
const tags = [{id: "1", title: "Writing"}, {id: "2", title: "Singing"}, {id: "3", title: "Dance"}];
const updateTags = useTags (tags)
const items = [{tags: "1", title: "USA", type: "text"}, {tags: "1, 2, 3", title: "Japan", type: "image"}, {tags: "2, 3", title: "Japan", type: "image"}];
console .log (
updateTags (items)
)
Note that I took a little liberty with the tags: "2,3" and tags: "Singing,Dance" formats, adding a little white space. It's trivial to take this out. But even better, if possible, would be to change this to use arrays for your tags.
You could take a real Map and map the values to the new objects.
var array1 = [{ id: "1", title: "Writing" }, { id: "2", title: "Singing" }, { id: "3", title: "Dance" }],
array2 = [{ tags: "1", title: "USA", type: "text" }, { tags: "1,2,3", title: "Japan", type: "image" }, { tags: "2,3", title: "Japan", type: "image" }],
tags = array1.reduce((m, { id, title }) => m.set(id, title), new Map),
result = array2.map(o => ({ ...o, tags: o.tags.split(',').map(Map.prototype.get, tags).join() }));
console.log(result);
.as-console-wrapper { max-height: 100% !important; top: 0; }

Categories

Resources