what is equivalent of numpy.repeat() in javascript - javascript

a=['a','b','c']
s=[2,5,1]
a= numpy.repeat(a,s)
a: ['a','a','b','b','b','b','b','c']
Is there something equivalent in JavaScript ?

Not a straight forward equivalent but you can use Array.flatMap and Array.from to repeat the value according to the index in the second array :
const a = ['a', 'b', 'c']
const s = [2, 5, 1]
const result = a.flatMap((e, ndx) => Array.from({
length: s[ndx]
}, () => e));
console.log({
result
});

Flatmap and fill the array.
const
repeat = (values, counts) => values.flatMap((v, i) => Array(counts[i]).fill(v)),
a = ['a', 'b', 'c'],
s = [2, 5, 1],
result = repeat(a, s);
console.log(...result);

Related

Omit keys from an object which are present in another array in javascript

I have an object like this -
const obj = {
'a': 1,
'b': 2,
'c': 3,
'd': 4,
'e': 5
}
and an array containing keys belonging to the object,
const arr = ['a', 'b', 'd']
I want to return an object similar to obj but it shouldn't contain the keys present in arr,
i.e., I want an object which will be
const result = {
'c': 3,
'e': 5
}
How can I achieve this via Javascript?
With the new Object.fromEntries, it's easy:
const result = Object.fromEntries(Object.entries(obj).filter(([k, _]) => !arr.includes(k)))
Without it, it takes a bit more effort:
const result = Object.entries(obj).reduce((tot, [k, v]) => {
if (!arr.includes(k)) {
tot[k] = v;
}
return tot;
}, {})
You can copy the object and delete the listed properties:
const obj = {a:1,b:2,c:3,d:4,e:5};
const arr = ['a', 'b', 'd'];
const res = {...obj};
for (let k of arr) delete res[k];
console.log(res);
Note that this has a time complexity that is almost linear in terms of the number of properties involved, O(m+nlogn) (if delete is O(logn)), while Aplet's answer would have a quadratic time complexity: O(mn).
Using Object.entries, you can generate [key, value] pair from object as array.
And based on that, using Array.reduce, you can get the result you want.
const obj = {
'a': 1,
'b': 2,
'c': 3,
'd': 4,
'e': 5
};
const arr = ['a', 'b', 'd'];
const result = Object.entries(obj).reduce((acc, cur) => {
if (!arr.includes(cur[0])) {
acc[cur[0]] = cur[1];
}
return acc;
}, {});
console.log(result);
Array#reduce solution:
const obj = {'a': 1,'b': 2,'c': 3,'d': 4,'e': 5};
const arr = ['a', 'b', 'd'];
const o = Object.keys(obj)
.reduce((s, a) => (arr.indexOf(a) > -1 ? s : s[a] = obj[a], s), {});
console.log(o);
You could destructure the object and get the rest of it without unwanted keys.
const
object = { a: 1, b: 2, c: 3, d: 4, e: 5 },
without = ['a', 'b', 'd'],
result = without.reduce((r, k) => ({ [k]: _, ...r } = r, r), object);
console.log(result);
Traverse the object using JavaScript for..in loop. Check property using array indexOf method. If property name is not present in the array then put the property with value in ret variable.
const obj = {
a: 1,
b: 2,
c: 3,
d: 4,
e: 5,
};
const arr = ["a", "b", "d"];
ret = {};
for (let x in obj) if (arr.indexOf(x) === -1) ret[x] = obj[x];
console.log(ret);
You can do this using Object#entries then filter out those entries which are not in the arr and using Object#fromEntries reconstruct the object:
const obj = {'a': 1,'b': 2,'c': 3,'d': 4,'e': 5}, arr = ['a', 'b', 'd'];
const filterObj = (obj, arr) => {
const dataSet = new Set(arr);
return Object.fromEntries(Object.entries(obj)
.filter(([k, v]) => !dataSet.has(k)))
};
console.log(filterObj(obj, arr));
Another way to filter the object with the supplied keys but without using Object#fromEntries is by using Object#assign.
We would just filter the entries which are not in the given array, then map them to objects and pass those as parameters to the Object#assign:
const obj = {'a': 1,'b': 2,'c': 3,'d': 4,'e': 5}, arr = ['a', 'b', 'd'];
const filterObj = (obj, arr) => {
const keySet = new Set(arr);
const filteredEntries = Object.entries(obj).filter(([k, v]) => !keySet.has(k));
return Object.assign({}, ...filteredEntries.map(([k, v]) => ({[k]: v})));
}
console.log(filterObj(obj, arr));

How to set the same value on multiple keys

How is it possible to set the same value on multiple keys? For example I have the following object:
const obj = {
a: 5,
b: 5,
c: 5,
d: 6
}
Is there any easy way for example lets say I have array of [a, b, c] (keys) and to spread them in object and set them as keys with same value. Point is to look more classy for example:
const keys =[a, b, c]
const obj = {
[...keys]: 5
}
I know this would throw error but looking for some shorthand to achieve this
Take the array of keys and map each to an entry of the key and the 5 value:
const keys = ['a', 'b', 'c'];
const obj = {
...Object.fromEntries(
keys.map(key => [key, 5])
),
d: 6
};
console.log(obj);
Something like this works:
const obj = {};
const value = 5;
['a', 'b', 'c'].forEach(key => obj[key] = value);
You can build a zip function which takes an array of keys and a array of values and returns an object where each key/value pair is taken from their respective index:
const zip =
(ks, vs) =>
ks.reduce((o, k, i) =>
(o[k] = vs[i], o), {});
zip(['a', 'b', 'c'], [5, 5, 5]);
//=> {a: 5, b: 5, c: 5}
If you need to generate an array of 5:
Array(3).fill(5);
//=> [5, 5, 5]
Another solution could take a spreading of Object.assign with a spreaded array of objects.
const
keys = ['a', 'b', 'c'],
obj = { ...Object.assign(...keys.map(k => ({ [k]: 5 }))), d: 6 };
console.log(obj);
function(item)
{
return Object.keys(item).reduce((a, b) => ({ ...a, [b]:5 }),{});
}

How to map an array of arrays into an array of objects with a given keys array?

From an array of keys and an array of arrays, like this:
const keys = ['foo', 'bar'];
const vals = [
['a', 'A'],
['b', 'B']
];
How to get an array of objects like below ?
[
{'foo' : 'a', 'bar' : 'A'},
{'foo' : 'b', 'bar' : 'B'}
]
Maybe using lodash ?
You can use loash's _.zipObject() to create an object from an array of keys and values for each value array inside your 2d array using the _.map() method:
const keys = ['foo', 'bar']
const vals = [
['a', 'A'],
['b', 'B']
];
const res = _.map(vals, arr => _.zipObject(keys, arr));
console.log(res);
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.15/lodash.min.js"></script>
If you prefer vanilla JS, then you could use Object.fromEntries() on a zipped array (created using .map()):
const keys = ['foo', 'bar']
const vals = [
['a', 'A'],
['b', 'B']
];
const res = vals.map(
arr => Object.fromEntries(arr.map((v, i) => [keys[i], v]))
);
console.log(res);
To be more generic, you can use Array.reduce() with index variable
const keys = ['foo', 'bar']
const values = [
['a', 'A'],
['b', 'B']
]
const mapped = values.map(val => val.reduce((acc, cur, i) => ({...acc, [keys[i]]: cur}),{}))
console.log(mapped)
With lodash/fp you can generate a function using _.flow(), that curries _.zipObject() with the keys, and the _.map() with the curried _.zipObject(), and then you can call it with vals to get the array of objects:
const fn = _.flow(_.zipObject, _.map);
const keys = ['foo', 'bar']
const vals = [
['a', 'A'],
['b', 'B']
];
const result = fn(keys)(vals);
console.log(result);
<script src='https://cdn.jsdelivr.net/g/lodash#4(lodash.min.js+lodash.fp.min.js)'></script>
You can do it simply using reduce.
let keys = ['foo', 'bar'];
let values = [
['a', 'A'],
['b', 'B']
];
const res = values.reduce((a, [first, second]) => {
return [...a, {[keys[0]]: first, [keys[1]]: second}];
}, []);
console.log(res);
.as-console-wrapper{min-height: 100%!important; top:0}
let dataKeys = ['foo', 'bar'];
let dataValues = [
['a', 'A'],
['b', 'B']
];
let transformed = dataValues.reduce((result,item)=>{
result.push(
dataKeys.reduce((r,dk,index)=>{
let o = {};
o[dk]= item[index];
return {...r, ...o}
},{})
)
return result
},[]);
console.log(JSON.stringify(transformed,null,2));

Is there any shorthand method to convert array of string array with header as first array to Objects of array?

Is there any shorthand method to convert array of string array with header as first array (Input as shown below) to Objects of array (as expected output shown below)
Using for loop we can achieve this, I am looking for any short hand and optimized solution to do this.
Let me know if is there any easy and optimized method to implement this.
Input
[
['fromAge', 'toAge', 'gender', 'institutionalRaf'],
[0, 10, 'F', '1.5'],
[11, 20, 'F', '2.5']
]
Expected Output :
[{
fromAge : 0,
toAge: 10,
gender: "F",
institutionalRaf : "1.5"
},
{
fromAge : 11,
toAge: 20,
gender: "F",
institutionalRaf : "2.5"
}
...
]
You can use map and reudce
Take the first element as header and rest of element as values
Loop through the values array for each element build a object with key from header and value from element
let data = [["fromAge","toAge","gender","institutionalRaf"],["1",'4','m','12'],["4",'12','f','22'],["10",'20','m','109']]
let [header,...values] = data
let final = values.map(v=> {
return v.reduce((op,inp,index)=>{
op[header[index]] = inp
return op
},{})
})
console.log(final)
You could separate the keys and the values and map the value as object with the keys.
var array = [['fromAge', 'toAge', 'gender', 'institutionalRaf'], [0, 10, 'F', '1.5'], [11, 20, 'F', '2.5']],
[keys, ...values] = array,
result = values.map(a => Object.assign(...keys.map((k, i) => ({ [k]: a[i] }))));
console.log(result);
I'd shift out the first array of keys, then .map to create entries and create the objects using Object.fromEntries:
const arr = [
['a', 'b', 'c'],
[1, 2, 3],
[4, 5, 6]
];
const keys = arr.shift();
const output = arr.map(values =>
Object.fromEntries(
values.map((value, i) => [keys[i], value])
)
);
console.log(output);
Object.fromEntries is a relatively new method. On older environments, either use a polyfill, or create the object with reduce instead:
const arr = [
['a', 'b', 'c'],
[1, 2, 3],
[4, 5, 6]
];
const keys = arr.shift();
const output = arr.map(values => (
values.reduce((a, value, i) => {
a[keys[i]] = value;
return a;
}, {})
));
console.log(output);
If keys are fixed we can use the simple approach like below
let arr=[
['fromAge', 'toAge', 'gender', 'institutionalRaf'],
[0, 10, 'F', '1.5'],
[11, 20, 'F', '2.5']
];
let arr1=arr.slice();
let x=arr1.shift();
let x1=arr1.map(a=>(
{
[x[0]]:a[0],
[x[1]]:a[1],
[x[2]]:a[2],
[x[3]]:a[3],
}
)
)
console.log(x1);
Use destructuring, map and reduce
const array = [
['fromAge', 'toAge', 'gender', 'institutionalRaf'],
[0, 10, 'F', '1.5'],
[11, 20, 'F', '2.5']
]
const [keys, ...values] = array
const result = values.map((value) => value.reduce((a, b, index) => ({...a, [keys[index]]: b}), {}), [])
console.log("result",result)

Two foreach replacement JS

Could you please recommend the more elegant way of handling these case?
const arr1 = [1, 2, 3];
const arr2 = ['a', 'b', 'c'];
const getCombinations = () => {
const combinations = [];
arr1.forEach(el1 => {
arr2.forEach(el2 => {
combinations.push({
el1,
el2
});
});
});
return combinations;
};
console.log(getCombinations());
You can use a Array.flatMap() with Array.map():
const arr1 = [1, 2, 3];
const arr2 = ['a', 'b', 'c'];
const getCombinations = (a, b) =>
a.flatMap(el1 => b.map(el2 => ({ el1, el2 })));
const result = getCombinations(arr1, arr2);
console.log(result);
You could take a slightly more dynamic aproach by taking the cartesian product first and then map the objects with the wanted properties.
const
cartesian = (a, b) => a.reduce((r, v) => r.concat(b.map(w => [].concat(v, w))), []),
takeKeys = keys => a => Object.assign(...a.map((v, i) => ({ [keys[i]]: v })))
array1 = [1, 2, 3],
array2 = ['a', 'b', 'c'],
result = [array1, array2]
.reduce(cartesian)
.map(takeKeys(['el1', 'el2']));
console.log(result);
.as-console-wrapper { max-height: 100% !important; top: 0; }

Categories

Resources