I have a array has a value of ['a', 'b', 'c', 'd', 'e'] now I want it to become a object that have it's value so I do some array mapping
const arrs = ['a', 'b', 'c', 'd', 'e']
let arrObj = arrs.map(arr => {
return {value: arr}
})
Now the value of arrObj is
[{value: 'a'}, {value: 'b'}, {value: 'c'}, {value: 'd'}, {value: 'e'}]
But what I want to do is to insert a object in the middle of each object that is inside the array that has a value of {operator: '+'} so the value of arrObj will be
[{value: 'a'}, {operator: '+'}, {value: 'b'}, {operator: '+'}, {value: 'c'}, {operator: '+'}, {value: 'd'}, {operator: '+'}, {value: 'e'}]
now, using javascript, how can I achive that function given that I'm setting a value of arrObj in array.map() ?
You could create a new array with a double length minus one and add the required values, depending on the index.
var values = ['a', 'b', 'c', 'd', 'e'],
result = Array.from(
{ length: values.length * 2 - 1 },
(_, i) => i % 2
? { operator: '+' }
: { value: values[i >> 1] }
);
console.log(result);
.as-console-wrapper { max-height: 100% !important; top: 0; }
One option is to map each element (but the last) to an array with that element and another with the +, then flatten:
const arrs = ['a', 'b', 'c', 'd', 'e'];
const transformed = arrs
.map((char, i) => (
i === arrs.length - 1
? [{ value: char }]
: [{ value: char }, { value: '+' }]
))
.flat();
console.log(transformed);
If + won't appear in the input array, then you can join by + initially, then split:
const arrs = ['a', 'b', 'c', 'd', 'e'];
const output = arrs
.join('+')
.split('')
.map(value => ({ value }));
console.log(output);
Use flatMap and return a pair from the callback. Finally, remove the extra element.
const arrs = ['a', 'b', 'c', 'd', 'e']
let arrObj = arrs.flatMap(x => [
{operator: '+'}, {value: x}
]).slice(1)
console.log(arrObj)
If your platform doesn't have flatMap yet, it's trivial to polyfill:
Array.prototype.flatMap = function(fn) {
return this.concat.apply([], this.map(fn))
}
Generic function:
let interleave = (ary, val) => ary.flatMap(x => [val, x]).slice(1);
//
let arrObj = interleave(
arrs.map(x => ( {value: x})),
{operator: '+'}
)
What about using reduce?
let arrObj = arrs.reduce((acc, curr, index) => {
if (index === arrs.length - 1) acc = [...acc, {value: curr}];
else acc = [...acc, {value: curr}, {operator: '+'}];
return acc;
}, [])
Concat your required object and deep flatten it like below:
var arrs = ['a', 'b', 'c', 'd','e'];
const arrObj = arrs.map((arr,i) => {
let item = [{value: arr}];
if(i < arrs.length-1)
item.push({operator: '+'});
return item;
});
console.log(flattenDeep(arrObj));
function flattenDeep(arr1) {
return arr1.reduce((acc, val) => Array.isArray(val) ? acc.concat(flattenDeep(val)) : acc.concat(val), []);
}
For more details take a look here: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/flat
Related
Below is an array containing some elements:
const arr = ['a', 'b', 'c', 'a', 'b', 'c', 'd']
So how can I create a new array where same elements are grouped together into a new array like this:
const arr = [['a','a'], ['b','b'], ['c','c'], ['d']]
Thank you for your time.
This can be achieved with the most generic of group by operations.
const arr = ['a', 'b', 'c', 'a', 'b', 'c', 'd'];
const grouped = Object.values(arr.reduce((a, n) => ((a[n] ??= []).push(n), a), {}));
console.log(grouped);
This is one way to do it. More explicit, but easier to understand and translate to other languages as well. Time: O(n), Space: O(n), n is number of elements in array
function process(arr) {
const map = arr.reduce((acc, e) => {
if (!acc.has(e)) {
acc.set(e, 0);
}
acc.set(e, acc.get(e) + 1);
return acc;
}, new Map())
const res = [];
for (const[k, v] of map.entries()) {
const localRes = [];
for (let i = 1; i <= v; i++) {
localRes.push(k);
}
res.push(localRes);
}
return res;
}
const arr = ['a', 'b', 'c', 'a', 'b', 'c', 'd']
console.log(process(arr));
Result:
[ [ 'a', 'a' ], [ 'b', 'b' ], [ 'c', 'c' ], [ 'd' ] ]
The idea is to sort the array in ascending order, then iterate over it and take if the last char and the current char are the same and put them in an inner-array else create new inner-array of that char, do this process of accumulating till for loop iterate overall characters.
["a","a","b","b","c","c","d"]
//sort and do algorithm
["a","a","b","b","c","c","d"]
//^---^ ^---^
[["a","a"],["b","b"],["c","c"],["d"]]
Implementation:
const arr = ["a", "b", "c", "a", "b", "c", "d"];
const chars = arr.sort((a, b) => a.localeCompare(b));
console.log(chars);
let res = [[]],
lastChar = chars[0];
for (char of chars) {
if (char == lastChar) {
res[res.length - 1].push(char);
} else {
res.push([char]);
lastChar = char;
}
}
Result:
console.log(res); //[["a","a"],["b","b"],["c","c"],["d"]]
anyway I can unpack an array into an object that each element of array as the key of object and value is 0? something like
const arr = ['a', 'b', 'c', 'd']
//I want to have
//const obj = {'a': 0, 'b': 0, 'c': 0}
Use Object.fromEntries combined with the array .map method:
const arr = ['a', 'b', 'c', 'd']
//I want to have:
//const obj = {'a': 0, 'b': 0, 'c': 0}
console.log(Object.fromEntries(arr.map(x => [x, 0])))
You could use Array.prototype.reduce() method to make your required object.
const arr = ['a', 'b', 'c', 'd'];
const ret = arr.reduce((prev, c) => {
const p = prev;
p[c] = 0;
return p;
}, {});
console.log(ret);
I have two objects that represent two SQL tables. Here are two simplified versions (they both might have many more properties):
const object1 = {
key1: [ 1, 1, 1, 2, 2, 3 ],
key2: ['a', 'b', 'c', 'a', 'c', 'b'],
prop3: ['A', 'B', 'C', 'D', 'E', 'F'],
}
const object2 = {
key1: [ 1, 1, 2],
key2: ['a', 'c', 'a'],
prop4: [10, 20, 30],
}
I would like to perform a left-join on key1 and key2. Something like:
select *
from object1 o1
left join object2 o2 on o1.key1 = o2.key1 and o1.key2 = o2.key2
Or in JS:
const object12 = {
key1: [ 1, 1, 1, 2, 2, 3 ],
key2: ['a', 'b', 'c', 'a', 'c', 'b'],
prop3: ['A', 'B', 'C', 'D', 'E', 'F'],
prop4: [10, null, 20, 30, null, null],
}
What's a convenient way to do this in JS? (using lodash is allowed)
const table = (entries, keys) => {
const toData = () => Object.fromEntries(keys.map(k => [k, entries.map(it => it[k] ?? null)]));
const join = (other, on) => table(
entries.map(entry => ({ ...entry, ...(other.entries.find(other => on(entry, other)) ?? {}) })),
[...keys, ...other.keys]
);
return { entries, keys, join, toData };
};
table.from = data => {
const keys = Object.keys(data);
const entries = [];
for(let i = 0; i < data[keys[0]].length; i++) {
const entry = entries[i] = {};
for(const key of keys)
entry[key] = data[key][i];
}
return table(entries, keys);
};
In action:
const table = (entries, keys) => {
const toData = () => Object.fromEntries(keys.map(k => [k, entries.map(it => it[k] ?? null)]));
const join = (other, on) => table(
entries.map(entry => ({ ...entry, ...(other.entries.find(other => on(entry, other)) ?? {}) })),
[...keys, ...other.keys]
);
return { entries, keys, join, toData };
};
table.from = data => {
const keys = Object.keys(data);
const entries = [];
for(let i = 0; i < data[keys[0]].length; i++) {
const entry = entries[i] = {};
for(const key of keys)
entry[key] = data[key][i];
}
return table(entries, keys);
};
const object1 = { key1: [ 1, 1, 1, 2, 2, 3 ], key2: ['a', 'b', 'c', 'a', 'c', 'b'], prop3: ['A', 'B', 'C', 'D', 'E', 'F'] };
const object2 = { key1: [ 1, 1, 2], key2: ['a', 'c', 'a'], prop4: [10, 20, 30] };
const result = table.from(object1)
.join(table.from(object2), (a, b) => a.key1 === b.key1 && a.key2 === b.key2)
.toData();
console.log(result);
I'd like to transform an array like the following:
const myArray = [ 'a', 'b', 'c', 'd', 'e', 'f' ];
to something like this:
const transformedArray = [ [ 'a', 'b' ], [ 'c', 'd' ], [ 'e', 'f' ] ];
The only way I see is to do it with a good old for loop, but is there a more elegant way to do it with Array.prototype functions ?
You could do something like this using reduce, Math.floor and %
const myArray = ['a', 'b', 'c', 'd', 'e', 'f']
const newArray = myArray.reduce((acc, a, i) => {
const index = Math.floor(i/2);
acc[index] = acc[index] || [];
acc[index][i % 2] = a
return acc
}, [])
console.log(newArray)
Math.floor(i/2) gets which of the inner array the item belongs to
i % 2 gets which postion of the inner array the item belongs to
You can use Array.from() to create an array of chunks:
const myArray = [ 'a', 'b', 'c', 'd', 'e', 'f', 'g' ];
const chunk = n => arr =>
Array.from({ length: Math.ceil(arr.length / n) }, (_, i) =>
myArray.slice(i * n, (i + 1) * n)
);
const log = arr => console.log(JSON.stringify(arr));
log(chunk(2)(myArray)); // [["a","b"],["c","d"],["e","f"],["g"]]
log(chunk(3)(myArray)); // [["a","b","c"],["d","e","f"],["g"]]
The solution below uses reduce to iterate over the items in the array. We use a modulo check on the index of the item to determine whether or not we need to start a new array.
The code adds in an object when it's inspecting an index which doesn't need to be formed into a new array. We later filter these objects out. There may be a more elegant way of doing this, but I feel it works out quite nicely.
const letters = [ 'a', 'b', 'c', 'd', 'e', 'f' ];
const splitIntoChunks = (arrayIn, size) => arrayIn.reduce(
(prev, curr, i) => [
...prev,
i % size === 0
? arrayIn.slice(i, i + size)
: { '__remove': true }
],
[],
).filter(x => !x['__remove'])
const result = splitIntoChunks(letters, 2)
console.dir(result)
One other solution that has been given to me which I find the most readable.
const myArray = [ 'a', 'b', 'c', 'd', 'e', 'f' ];
const transformedArray = Array(myArray.length / 2).fill().map((_, i) => [myArray[i * 2], myArray[i * 2 + 1]]);
console.log(transformedArray);
How can I create an object from two arrays without using loops in javascript.
example:
array1 = [1,2,3,4,5];
array2 = [A,B,C,D,E];
I want from below object
obj = {
'1': 'A',
'2': 'B',
'3': 'C',
'4': 'D',
'5': 'E',
}
Thanks in advance
var obj = {}
array1 = [1, 2, 3, 4, 5];
array2 = ['A', 'B', 'C', 'D', 'E'];
array1.forEach(function(value, index) {
obj[value] = array2[index];
});
console.log(obj);
Try to use $.each() to iterate over one of that array and construct the object as per your requirement,
var array1 = [1,2,3,4,5],array2 = ['A','B','C','D','E'];
var obj = {};
$.each(array2,function(i,val){
obj[array1[i]] = val;
});
DEMO
An ES6, array reduce solution.
const array1 = [1, 2, 3, 4, 5];
const array2 = ['A', 'B', 'C', 'D', 'E'];
const resultMap = array1.reduce(
(accumulator, value, index) => Object.assign(accumulator, {
[value]: array2[index],
}), {}
);
console.log(resultMap);
just for fun created something like this without using any iteration methods.
const array1 = [1,2,3,4,5];
const array2 = ['A','B','C','D','E'];
let combineKeyValueProxy = new Proxy({}, {
set: function(target, prop, value, receiver) {
target[array1[prop]] = value;
return true
}
});
const output = Object.assign(combineKeyValueProxy, array2);
console.log(output) // Proxy {1: "A", 2: "B", 3: "C", 4: "D", 5: "E"}