Combine the result of two input fields with JavaScript? - javascript

I have as a result from an input form a couple of strings and I want them to convert them, so they fit as data for my ajax-request. I am looking for an easy way, but I can't get it right. Basically I want to convert/map this array:
[
{ name: "[1][apples]", value: "2" }
{ name: "[1][melons]", value: "1" }
{ name: "[2][apples]", value: "2" }
{ name: "[2][melons]", value: "4" }
{ name: "[3][apples]", value: "3" }
{ name: "[3][melons]", value: "2" }
]
into
[{"id": 1, "apples": 2, "melons": 1}, {"id": 2, "apples": 2, "melons": 4}, {...}]
Any idea? I would appreciate some hint? I could't not find an easy solution via html though.
Thanks

you can use a for loop to access each element and display them.
Refer to this link. For loop in multidimensional javascript array

Firstly, I have replaced the square brackets using a regular expression and formed a new array. After that, I have merged object having same ID using spread operator.
You can refer to the code below which solves this problem.
let array = [
{ name: "[1][apples]", value: "2" },
{ name: "[1][melons]", value: "1" },
{ name: "[2][apples]", value: "2" },
{ name: "[2][melons]", value: "4" },
{ name: "[3][apples]", value: "3" },
{ name: "[3][melons]", value: "2" }];
let newArray = [];
let result = [];
array.forEach((obj, i) => {
let nameArray = obj.name.replace(/[\[\]']+/g, ' ').trim().split(' ');
let o = {};
o['id'] = parseInt(nameArray[0]);
o[nameArray[1]] = obj.value;
newArray.push(o);
});
for(let i = 0; i< newArray.length; i++) {
for(let j = i+1; j < newArray.length; j++) {
if(newArray[i].id === newArray[j].id) {
let o = {...newArray[i], ...newArray[j]};
result.push(o);`enter code here`
}
}
}
console.log('Final result', result);

Thanks for the input. I think my question needed to be more specific:
(1) Yes, they are always in order.
(2) My names of my input-tags in html appear to be an multidimensional array. This is not the case! I tried something, but it turned out to be for php.
I found the follow workaround:
function apiAdapter() {
var arrayToCopy = $("#formsteps").serializeArray();
var copiedArray = [];
for (let i = 0; i < arrayToCopy.length; i += 2) {
var id = arrayToCopy[i].name.slice(arrayToCopy[i].name.indexOf('[') + 1, arrayToCopy[i].name.indexOf(']'));
copiedArray.push({ "id": id, "apples": arrayToCopy[i].value, "melons": arrayToCopy[i + 1].value })
}
return copiedArray;
}
As I am new to JavaScript I always look for better solutions. So thanks again for your posts.

Related

How to add label to js array?

Hi I am looking to create an array that looks similar to this
const userList = {
123: "Tom",
124: "Michael",
125: "Christin",
};
it contains both value and label, what I tried so far
let raw = []
for (let x in data) {
raw.push(data[x].facility_name : data[x].id)
}
but it didn't work because "," was expected, if someone can help please
You are confusing arrays and objects. You need to add a key to an object not push. I kept it as a for in loop, but a for of loop would make more sense.
const data = [
{ id: 1, facility_name: "foo1" },
{ id: 2, facility_name: "foo2" },
{ id: 3, facility_name: "foo3" }
];
let raw = {};
for (let x in data) {
raw[data[x].id] = data[x].facility_name;
}
console.log(raw);
How I would code it using reduce.
var data = [
{ id: 1, facility_name: "foo1" },
{ id: 2, facility_name: "foo2" },
{ id: 3, facility_name: "foo3" }
];
const raw = data.reduce(function (acc, facility) {
acc[facility.id] = facility.facility_name;
return acc;
}, {})
console.log(raw);
IF your data has nested objects then you might do this:
let raw = {};
for(x in data)
{
raw[data[x].facility_name] = data[x].id;
}
This is useful when you want to get rid of duplicates.

javascript how to form an array of objects by combining first Array and their values are in other arrays

Im facing a small issue in Javascript.
I have below Arrays.
var labels = ["labelOne", "labelTwo"];
var values1 = ["89", "9"];
var values2 = ["32", "78"];
Here we can place n number of values arrays like value3,value4....
Now how can i form an array of Objects by combining labels Array and their values are in values arrays. Im expecting the below output after combining above 3 arrays..
var mainArray = [{
label:"labelOne",
value:"89"
},
{
label:"labelTwo",
value:"9"
},
{
label:"labelOne",
value:"32"
},
{
label:"labelTwo",
value:"78"
}]
Can someone please help me to achieve the above output.
Thank you in advance
All that you need is a variable to know how many arrays should be added and access them in a loop using the advantage that Javascript lets you get them like this: window['variableName'] when they are defined in global scope.
var labels = ["labelOne", "labelTwo"];
var values1 = ["89", "9"];
var values2 = ["32", "78"];
var mainArray = [];
// Define a variable to know how many arrays should be added
var maxValues = 2;
function addValues(values) {
// Create new elements and push them into mainArray
mainArray.push({label:labels[0], value:values[0]});
mainArray.push({label:labels[1], value:values[1]});
}
// Do a loop from 1 to maxValues
for(let i = 1; i <= maxValues; i++) {
// Call the function with dynamic variable name
addValues(window['values' + i]);
}
console.log(mainArray);
If the order of your array isn't critical (and then, you might sort it later if it is), you can do like this:
const output = labels.map((label, index) => {
return [{ label, value: values1[index] }, { label, value: values2[index] }];
}).flat();
The map step, will give you an array like this:
[
[{ label: 'labelOne', value: 89 }, { label: 'labelOne', value: 32 }],
[{ label: 'labelTwo', value: 9}, { label: 'labelTwo', value: 78}]
]
By then calling flat, it'll transform it into:
[{ label: 'labelOne', value: 89 }, { label: 'labelOne', value: 32 }, { label: 'labelTwo', value: 9}, { label: 'labelTwo', value: 78}]
Which is what you wanted, from here you can sort the array if that matters for your use case.

problems with for loop inside another for loop Javascript

I have problems in going through these two for loops, I need to get the same elements from the first array within the cycle, but the values ​​are being repeated. I know that they are repeated depending on the data of the second array.
I tried to make comparisons but I could not get the result I want.
var array = [
{
grouper: 1
},
{
grouper: 2
},
{
grouper: 3
},
{
grouper: 4
},
];
var array2 = [
{
value: 1,
grouper: 1,
status: 100
},
{
value: 2,
grouper: 2,
status: 100
},
{
value: 3,
grouper: 3,
status: 100
}
];
for(var i = 0; i<array.length; i++){
for(var j = 0; j<array2.length; j++){
if(array2[j].grouper == array[i].grouper){
console.log(array[i].grouper+'-'+array2[j].value);
}
}
}
This is the result I want, I need all the groupers from the first array and the values from the second array:
1-1
2-2
3-3
4-
The grouper 4, does not have value, but I need to show it.
I need the second array because I'm going to compare with the data from the second array
I do not know if I am doing the process wrong. I hope you can help me.
You could simply track if there was a match (variable shown), and if there were not any, display a "half" line:
var array = [{grouper: 1},{grouper: 2},{grouper: 3},{grouper: 4},];
var array2 = [
{value: 1, grouper: 1, status: 100},
{value: 2, grouper: 2, status: 100},
{value: 3, grouper: 3, status: 100}
];
for(var i = 0; i<array.length; i++){
var shown=false;
for(var j = 0; j<array2.length; j++){
if(array2[j].grouper == array[i].grouper){
console.log(array[i].grouper+'-'+array2[j].value);
shown=true;
}
}
if(!shown){
console.log(array[i].grouper+"-");
}
}
First of all, with the example you provided I believe you want to get back:
1,2,3
There is no 4th object inside of array2, so your conditional (array2[j].grouper == array[i].grouper will never evaluate to true.
The question here is whether you are always comparing the same indexes? In this example, you're comparing array[0] to array2[0] to see if grouper in array equals grouper in array2... that's it????
In that case you just do one loop:
for (var i = 0; i < array.length; i++) {
if (array[i].grouper == array2[i].grouper) {
console.log(array[i].grouper+'-'+array2[j].value);
}
}
#FabianSierra ... with your provided example one just needs to handle the not fulfilled if clause/condition in the most inner loop.
A more generic approach additionally might take into account changing field names (keys). Thus a function and Array.reduce / Array.find based approach provides better code reuse. An example implementation then might look similar to that ...
var array = [{ // in order.
grouper: 1
}, {
grouper: 2
}, {
grouper: 3
}, {
grouper: 4
}];
var array2 = [{ // not in the order similar to `array`.
value: 22,
grouper: 2,
status: 200
}, {
value: 33,
grouper: 3,
status: 300
}, {
value: 11,
grouper: 1,
status: 100
}];
function collectRelatedItemValuesByKeys(collector, item) {
var sourceKey = collector.sourceKey;
var targetKey = collector.targetKey;
var targetList = collector.targetList;
var resultList = collector.result;
var sourceValue = item[sourceKey];
var targetValue;
var relatedItem = targetList.find(function (targetItem) {
return (targetItem[sourceKey] === sourceValue);
});
if (typeof relatedItem !== 'undefined') {
targetValue = relatedItem[targetKey];
} else if (typeof targetValue === 'undefined') {
targetValue = ''; // `relatedItem` does not exist.
}
resultList.push([sourceValue, targetValue].join('-'));
return collector;
}
var resultList = array.reduce(collectRelatedItemValuesByKeys, {
sourceKey: 'grouper',
targetKey: 'value',
targetList: array2,
result: []
}).result;
console.log('resultList : ', resultList);
resultList = array.reduce(collectRelatedItemValuesByKeys, {
sourceKey: 'grouper',
targetKey: 'status',
targetList: array2,
result: []
}).result;
console.log('resultList : ', resultList);
.as-console-wrapper { max-height: 100%!important; top: 0; }

Create new array from iterating JSON objects and getting only 1 of its inner array

See jsfiddle here: https://jsfiddle.net/remenyLx/2/
I have data that contains objects that each have an array of images. I want only the first image of each object.
var data1 = [
{
id: 1,
images: [
{ name: '1a' },
{ name: '1b' }
]
},
{
id: 2,
images: [
{ name: '2a' },
{ name: '2b' }
]
},
{
id: 3
},
{
id: 4,
images: []
}
];
var filtered = [];
var b = data1.forEach((element, index, array) => {
if(element.images && element.images.length)
filtered.push(element.images[0].name);
});
console.log(filtered);
The output needs to be flat:
['1a', '2a']
How can I make this prettier?
I'm not too familiar with JS map, reduce and filter and I think those would make my code more sensible; the forEach feels unnecessary.
First you can filter out elements without proper images property and then map it to new array:
const filtered = data1
.filter(e => e.images && e.images.length)
.map(e => e.images[0].name)
To do this in one loop you can use reduce function:
const filtered = data1.reduce((r, e) => {
if (e.images && e.images.length) {
r.push(e.images[0].name)
}
return r
}, [])
You can use reduce() to return this result.
var data1 = [{
id: 1,
images: [{
name: '1a'
}, {
name: '1b'
}]
}, {
id: 2,
images: [{
name: '2a'
}, {
name: '2b'
}]
}, {
id: 3
}, {
id: 4,
images: []
}];
var result = data1.reduce(function(r, e) {
if (e.hasOwnProperty('images') && e.images.length) r.push(e.images[0].name);
return r;
}, [])
console.log(result);
All answers are creating NEW arrays before projecting the final result : (filter and map creates a new array each) so basically it's creating twice.
Another approach is only to yield expected values :
Using iterator functions
function* foo(g)
{
for (let i = 0; i < g.length; i++)
{
if (g[i]['images'] && g[i]["images"].length)
yield g[i]['images'][0]["name"];
}
}
var iterator = foo(data1) ;
var result = iterator.next();
while (!result.done)
{
console.log(result.value)
result = iterator.next();
}
This will not create any additional array and only return the expected values !
However if you must return an array , rather than to do something with the actual values , then use other solutions suggested here.
https://jsfiddle.net/remenyLx/7/

Javascript: How convert array of objects to object with sorted unique arrays?

Have data that has this kind of structure:
$input = [ { animal: 'cat', name: 'Rocky', value: 1 },
{ animal: 'cat', name: 'Spot', value: 2 },
{ animal: 'dog', name: 'Spot', value: 3 } ];
Need fastest possible method for converting to this format:
$output = { animal: [ 'cat', 'dog' ],
name: [ 'Rocky', 'Spot' ],
value: [ 1, 2, 3 ] };
The output should have keys equal to each of the keys in each object from the input. And the output values should be arrays with the sorted unique values. I found a few ways to do it using nested loops, but slower than I would like. With 30,000 elements to the input array with 8 keys for each of the objects, the best I have been able to do is 300ms in Chrome. Would like to get down to 100ms. Is there any faster method using a map or reduce?
Yet another way for modern browsers:
$input.reduce(function(acc, obj) {
Object.keys(obj).forEach(function(k) {
acc[k] = (acc[k] || []).concat(obj[k])
})
return acc
},{})
Here's one way.
$input = [ { animal: 'cat', name: 'Rocky', value: 1 },
{ animal: 'cat', name: 'Spot', value: 2 },
{ animal: 'dog', name: 'Spot', value: 3 } ];
$output = {animal:{},name:{},value:{}};
$input.forEach(function(v,i) {
$output.animal[v.animal] = 1;
$output.name[v.name] = 1;
$output.value[v.value] = 1;
});
$output.animal = Object.keys($output.animal);
$output.name = Object.keys($output.name);
$output.value = Object.keys($output.value);
It prevents having to test each Array every time. You can performance compare to see if it helps.
live example: http://jsfiddle.net/TJVtj/1/
If you don't want to hardcode the keys, you can make the solution generic.
var keys = Object.keys($input[0]),
$output = {};
keys.forEach(function(v) {
$output[v] = {};
});
$input.forEach(function(v) {
keys.forEach(function(vv) {
$output[vv][v[vv]] = 1;
});
});
keys.forEach(function(v) {
$output[v] = Object.keys($output[v]);
});
live example: http://jsfiddle.net/TJVtj/2/
Warning. All the values will be strings since they're fetched as object keys.
function inArray(needle, haystack) {
var length = haystack.length;
for(var i = 0; i < length; i++) {
if(haystack[i] == needle) return true;
}
return false;
}
Above function is used to check duplicates
$output={};
for(i=0; i< $input.length; i++)
{
if(!$output.animal) $output.animal=[];
if(!$output.name) $output.name=[];
if(!$output.value) $output.value=[];
var ani=$input[i];
if(ani.animal && !inArray(ani.animal, $output.animal)) $output.animal.push(ani.animal);
if(ani.name && !inArray(ani.name, $output.name)) $output.name.push(ani.name);
if(ani.value) $output.value.push(ani.value);
}
DEMO.
// If you don't know the objects all have the same keys you need to look at each one-
var output= {},
input= [{
animal:'cat', name:'Rocky', value:1
},{
animal:'cat', name:'Spot', value:2
},{
animal:'dog', name:'Spot', value:3
}];
input.forEach(function(itm){
for(var p in itm){
if(itm.hasOwnProperty(p)){
if(!output[p]) output[p]= [];
if(output[p].indexOf(itm[p])== -1) output[p].push(itm[p]);
}
}
});
Run.expose(output)// nonstandard object to string method
// returned value: (String)
{
animal:[
'cat',
'dog'
],
name:[
'Rocky',
'Spot'
],
value:[
1,
2,
3
]
}
Try Underscore, it's magnificent with this kind of tasks)

Categories

Resources