Related
I have an array of elements containing iPhone models and 4 values that come after it, like this:
const arr = ['ip6s+', '35', '15', '10', '10', 'ip7', '40', '20', '15', '15']
I want to turn this into an object that looks like this:
const Obj = {
'ip6s+': ['35', '15', '10', '10'],
'ip7+' : ['90', '60', '35', '30']
}
Where the first object is the phone model and every fourth is its values. How to do that?
You can use slice:
const arr = ['ip6s+', '35', '15', '10', '10','ip7', '40', '20', '15','15'];
const obj = {};
const n = 4; // the number of values after the model name
for (var i = 0; i < arr.length; i += n + 1) {
obj[arr[i]] = arr.slice(i + 1, i + n + 1);
}
console.log(obj);
You could also use reduce()
const arr = ['ip6s+', '35', '15', '10', '10','ip7', '40', '20', '15','15']
let lastCurr = null;
const result = arr.reduce( ( res, curr, ix ) => {
if( 0 == ix % 5 ){
res[ curr ] = [];
lastCurr = curr;
}else
res[ lastCurr ].push( curr );
return res;
}, {} )
If your keys are always supposed to be isNaN and first value always corresponds to key, than you can do something like this, this will be more dynamic in case there are dynamic number of elements between two keys
const arr = ['ip6s+', '35', '15', '10', '10', 'ip7', '40', '20', '15', '15']
let getDesiredFormat = (arr) => {
let currentKey = arr[0]
let final = arr.reduce((op, inp) => {
if (isNaN(inp)) {
op[inp] = []
currentKey = inp
} else {
op[currentKey].push(inp)
}
return op
}, {})
return final
}
console.log(getDesiredFormat(arr))
If the array starts with an item that starts with "ip" and starting with that is the trigger for a new key in the object, you could use startswith.
This allows a variable number of items after ip.
const arr = ['ip6s+', '35', '15', '10', '10', 'ip7', '40', '20', '15', '15'];
const obj = {};
let currKey = arr.slice(0, 1);
arr.forEach(s => s.startsWith("ip") ? (currKey = s, obj[s] = []) : obj[currKey].push(s));
console.log(obj);
Use slice method, also the following example should work no matter how many elements in the array :
this should work also if there are elements before 'ip6s+' BUT the 'ip6s+' must always precede 'ip7'.
const arr = ['some', 'elemnts', 'in', 'front', 'ip6s+', '35', '15', 'abc', '80', '58', '10', '10', 'ip7', '40', '20', '15', '15', '100', 'xyz'],
l = arr.length,
ip6sIndex = arr.indexOf('ip6s+'),
ip7Index = arr.indexOf('ip7'),
obj = {};
obj[arr[ip6sIndex]] = arr.slice(ip6sIndex + 1, ip7Index); /** get the items after 'ip6s+' **/
obj[arr[ip7Index]] = arr.slice(-(l - ip7Index) + 1); /** get the items after 'ip7' **/
console.log(obj);
I have two arrays
let arr1 = [{'id': 'ee', 'seat': '12'},
{'id': 'aa', 'seat': '8'}
]
let arr2 = [
{'id': 's22', 'num': ''},
{'id': '2s2', 'num': ''}
]
I want to copy seat values from arr1 to num property at arr2, but I only get last arr1 seat value in for loop.
for( let i = 0; i <= arr1.length; i++) {
for( let x = 0; x <= arr2.length; x++) {
arr2[x]['num'] = arr1[i]['seat'];
}
}
console.log(arr2);
Iterate arr2 with Array.forEach(), and take the respective seat value by index from arr1:
const arr1 = [{'id': 'ee', 'seat': '12'},{'id': 'aa', 'seat': '8'}]
const arr2 = [{'id': 's22', 'num': ''},{'id': '2s2', 'num': ''}]
arr2.forEach((o, i) => o.num = arr1[i].seat)
console.log(arr2)
You need just a single loop and check if the index of the array if is (only) smaller than the length of the minimum of both arrays.
If the index get the length of an array, the access returns undefined, because this element is not in the array.
A further access to a property of this throws an error:
Unable to get property 'seat' of undefined or null reference
var arr1 = [{ id: 'ee', seat: '12' }, { id: 'aa', seat: '8' }],
arr2 = [{ id: 's22', num: '' }, { id: '2s2', num: '' }],
i, l;
for (i = 0, l = Math.min(arr1.length, arr2.length); i < l; i++) {
arr2[i].num = arr1[i].seat;
}
console.log(arr2);
You can do it in just one for loop.
for(let i = 0; i < arr1.length; i++) {
arr2[i].num = arr1[i].seat;
}
Hope this helps!
Assuming you want to match indices, this should do it.
const arr1 = [
{'id': 'ee', 'seat': '12'},
{'id': 'aa', 'seat': '8'}
]
const arr2 = [
{'id': 's22', 'num': ''},
{'id': '2s2', 'num': ''}
]
const result = arr2.map((e, i) => ({...e, ...{num: arr1[i].seat}}))
console.log(result)
If you want all of the seats in each num, it wouldn't be much harder.
I have 4 arrays of the following format
arr1 = ['Hello', 'World', 'Hi']
arr2 = ['1', '2', '3']
arr3 = ['foo', 'bar', 'foobar']
arr4 = ['10', '20', '30']
I am trying to add each value at index[i] to a new object, the object looks like this
obj = {
title: '',
score: '',
description: '',
value: '',
}
For each indexed value in the array I would like to push it to a new instance of the obj object so I can end up with this
objects = [
{
title: 'Hello',
score: '1',
description: 'foo',
value: '10',
},
{
title: 'World',
score: '2',
description: 'bar',
value: '20',
},
{
title: 'Hi',
score: '3',
description: 'foobar',
value: '30',
}
]
So far I have been trying something like
objects = []
arr1.forEach((key, i) => objects[key] = arr2[i])
But that is assigning them as arr1val : arr2val
I will ultimately be setting this to state in my react app and passing it to another component as props to render on the page. The data is coming in from 3 different APIs, I am doing this to try and standardise the data received from each API so my component can use the data to render an articles list and user can switch between feeds.
Map by the index of element across all arrays, also use map not forEach:
const objects = arr1.map((element, index) => (
{title: element, score: arr2[index], description: arr3[index], value: arr4[index]}
))
Live demo is below:
const arr1 = ['Hello', 'World', 'Hi']
const arr2 = ['1', '2', '3']
const arr3 = ['foo', 'bar', 'foobar']
const arr4 = ['10', '20', '30']
const objects = arr1.map((element, index) => (
{title: element, score: arr2[index], description: arr3[index], value: arr4[index]}
))
console.log(objects)
This code also works:
var arr = [];
for(var i=0; i<arr1.length; i++) {
arr[i] = {};
arr[i].title = arr1[i];
arr[i].score = arr2[i];
arr[i].description = arr3[i];
arr[i].value = arr4[i];
}
I suggest to use an array of arrays and another array for the keys. This allows an arbitrary count of arrays and keys to use for transforming the data into an array of objects with hte wanted properties.
var array1 = ['Hello', 'World', 'Hi'],
array2 = ['1', '2', '3'],
array3 = ['foo', 'bar', 'foobar'],
array4 = ['10', '20', '30'],
keys = ['title', 'score', 'description', 'value'],
result = [array1, array2, array3, array4].reduce(function (r, a, i) {
a.forEach(function (v, j) {
r[j] = r[j] || {};
r[j][keys[i]] = v;
});
return r;
}, []);
console.log(result);
.as-console-wrapper { max-height: 100% !important; top: 0; }
If you don't want to type the property names twice,
you could do like this:
const descriptor = {
title: arr1,
score: arr2,
description: arr3,
value: arr4
};
const objects = arr1.map((tmp, i) => {
var o = {};
Object.keys(descriptor).forEach(name => o[name] = descriptor[name][i]);
return o;
});
A reducer method would be in place I suppose
const arr1 = ['Hello', 'World', 'Hi', 'Hello2', 'World2', 'Hi2'];
const arr2 = ['1', '2', '3', '11', '22', '33'];
const arr3 = ['foo', 'bar', 'foobar', 'sea', 'shell', 'sea weed'];
const arr4 = ['10', '20', '30', '100', '200', '300'];
const arrays2Objects = arr1.reduce( (obj, next, i) =>
obj.concat({title: next, score: arr2[i], description: arr3[i], value: arr4[i]}),
[]
);
console.log(arrays2Objects);
I try to use an array to iterate all posibilities of combine n element from an array:
array = ["9","0","1","2"];
For example the function combine(array,iter) with iter=2 shuld return:
["90","09","91","19","92","29","01","10","02","20","12","21","99","00","11","22"]
Parameters are define:
array: original array with all elements to combine.
iter: number of elements to result in combine with duplicates.
I try using yield, but without results, the quantity of elements are correct but, the value is wrong:
//Thank you to le_m for the code in ES6!
function* express(tokens, size) {
if (size < 1) yield [];
else
for (var item of tokens) {
for (var combination of express(tokens, size - 1)) {
yield combination.concat(item);
}
}
}
array = ["9","0","1","2"];
for (iter of express(array,2)) {
console.log(iter)
}
Console Output:
[ '9', '9' ]
[ '0', '9' ]
[ '1', '9' ]
[ '2', '9' ]
[ '9', '0' ]
[ '0', '0' ]
[ '1', '0' ]
[ '2', '0' ]
[ '9', '1' ]
[ '0', '1' ]
[ '1', '1' ]
[ '2', '1' ]
[ '9', '2' ]
[ '0', '2' ]
[ '1', '2' ]
[ '2', '2' ]
You want to generate all possible combinations of a given length. There are n^length combinations in total. To avoid the possibly huge memory requirement, I recommend using a generator function:
// Return all combinations of 'length' elements from array:
function* combine(array, length) {
if (length < 1) yield [];
else for (let element of array) {
for (let combination of combine(array, length - 1)) {
yield combination.concat(element);
}
}
}
// Example:
console.log(...combine(["9", "0", "1", "2"], 2));
What is the most efficient way to compare two javascript arrays and create two new arrays of missing and new elements? Array elements will be always strings or numbers and it is not 100% sure that they will be sorted in any way.
var old_array = ['11', '13', '14', '18', '22', '23', '25'];
var new_array = ['11', '13', '15', '16', '17', '23', '25', '31'];
var missing_elements = [];
var new_elements = [];
/*
* some magic goes here
* which compares
* new_array with old_array
*/
console.log(missing_elements); // would produce ['14', '18', '22']
console.log(new_elements); // would produce ['15', '16', '17', '31']
Thanks a bunch!
The code to Drew Noakes' solution:
var old_array = ['11', '13', '14', '18', '22', '23', '25'];
var new_array = ['11', '13', '15', '16', '17', '23', '25', '31'];
var missing_elements = _.difference(old_array, new_array);
var new_elements = _.difference(new_array, old_array);
console.log(missing_elements); // would produce ['14', '18', '22']
console.log(new_elements); // would produce ['15', '16', '17', '31']
I would use Underscore.js's intersection and difference functions.
Sorting will be the most efficient (assuming you don't have any other preconditions to base an optimization on):
var old_array_sorted = old_array.slice().sort(); // slicing for not mutating
var new_array_sorted = new_array.slice().sort(); // the original array
for (var o=0, n=0; o<old_array_sorted.length && n<new_array_sorted.length; ) {
if (old_array_sorted[o] < new_array_sorted[n])
missing_elements.push ( old_array_sorted[o++] );
else if (old_array_sorted[o] > new_array_sorted[n])
new_elements.push( new_array_sorted[n++] );
else
n++, o++;
}
[].push.apply(missing_elements, old_array_sorted.slice(o));
[].push.apply(new_elements, new_array_sorted.slice(n));