How to implement rxjs zip operator for array of arrays? - javascript

I have a source that gives an array of arrays. All arrays has the same number of element(s).
How can I use rxjs zip operator to transform the source array as described below so I could easily do the mapping? Thanks in advance!
var source = Rx.Observable.from([[1, 2, 3], ["a", "b", "c"], ["do", "re", "mi"]]);
// I would like to transform to:
// [[1, "a", "do"], [2, "b", "re"], [3, "c", "mi"]]

You can convert each array to an Observable, then zip:
var myArrays = [
[1, 2, 3],
['a', 'b', 'c'],
['do', 're', 'mi']
];
var myObservables = myArrays.map(xs => Rx.Observable.from(xs));
var zipped$ = Rx.Observable.zip(myObservables);
zipped$.subscribe(x => console.log(x));
Alternatively, you can forego the conversion from Array to Observable and use lodash's zip to combine the arrays:
var zipped = _.zip(...myArrays)

Related

Ramda JS partition array into multiple sub-arrays based on indices

I would like to take an array and split it into a dictionary of sub-arrays based on another array of indices:
const arr = ["A", "B", "C", "D", "E"];
const indices = [0, 0, 1, 0, 3];
// Would like to do something like this:
R.split(indices, array) // { "0": ["A", "B", "D"], "1": ["C"], "3": ["E"] }
Is there an elegant way to do this in Ramda?
Use R.zip combine the arrays to an array of values/indices pairs. Group by the indices, and then take only the values from the pairs:
const { pipe, zip, groupBy, last, map, head } = R
const fn = pipe(
zip, // combine the arrays to an array of value/indice pairs
groupBy(last), // group by the indices
map(map(head)) // take only the values from the pairs
)
const arr = ["A", "B", "C", "D", "E"]
const indices = [0, 0, 1, 0, 3]
const result = fn(arr, indices)
console.log(result)
<script src="https://cdnjs.cloudflare.com/ajax/libs/ramda/0.28.0/ramda.min.js" integrity="sha512-t0vPcE8ynwIFovsylwUuLPIbdhDj6fav2prN9fEu/VYBupsmrmk9x43Hvnt+Mgn2h5YPSJOk7PMo9zIeGedD1A==" crossorigin="anonymous" referrerpolicy="no-referrer"></script>

How to create permutations of tuple-like list where identical integer pairs are not permuted

I have this array of arrays, where the inner arrays are uniformly structured (“tuple-like”) with a unique ID (a string) and a non-unique integer:
[
["A",2],
["B",1],
["C",1]
]
I need the JavaScript function to create the list of permutations below, that does not permute tuples with the same integer value:
[
["A", "B", "C"],
["B", "A", "C"],
["B", "C", "A"]
]
Quoting user pilchard in the comments below, I'm trying to permute “by the second index and avoid duplicates”.
The list should therefore not include these permutations:
[
["A", "C", "B"], // integers same as in ["A", "B", "C"]
["C", "A", "B"], // integers same as in ["B", "A", "C"]
["C", "B", "A"] // integers same as in ["B", "C", "A"]
]
Also, it is preferable to avoid “movement” inside the array. Therefore, ["A", "B", "C"] is a better permutation than ["A", "C", "B"]
In the simplest scenario, the input could be this:
[
["A",1],
["B",1],
["C",1],
["D",1]
]
The result should simply be 1 permutation, as opposed to the 24 that is the result when also permuting identical integers:
[
["A", "B", "C", "D"]
]
Again, “movement” inside the array should be avoided, so ["A", "B", "C", "D"] is the preferred alternative.
Instead of operating on an array of characters, operate on an array of groups of characters. You can take any of these solutions, and instead of removing the chosen character from the input to put it into the output, remove the first character of the chosen group and remove the group only when it's empty.
function groupPermutations(groups) {
if (!groups.length) return [[]];
return groups.flatMap((group, i) => {
// assert(group.length > 0)
const [val, ...rest] = group;
const remaining = rest.length
? [...groups.slice(0,i), rest, ...groups.slice(i+1)]
: [...groups.slice(0,i), ...groups.slice(i+1)];
return groupPermutations(remaining).map(p => [val, ...p]);
});
}
console.log(groupPermutations(["A", "BC"]));
console.log(groupPermutations(["ABCD"]));
Now you only need a trivial conversion of your tuple input format to the grouping:
const pairs = [
["A",2],
["B",1],
["C",1],
];
const byInteger = new Map();
for (const [val, key] of pairs) {
if (!byInteger.has(key)) byInteger.set(key, []);
byInteger.get(key).push(val);
}
const groups = Array.from(byInteger.values());
console.log(groupPermutations(groups));

javascript equivalent to [x for x in array]

Is there any operation in Javascript just like [x for x in array] in python?
For example, I'm using javascript to reading a json file where there're dozens of (key, value) pairs needed to be handled(or transformed into other format). And I thought working in this way is stupid:
let transformed = []
for (let key in json){
transformed = [ /* doing some transform*/ ]
}
Is there anything like:
let transformed = [
lambda function1(key), lambda function2(value) for key, value in json
]
Thanks in advance.
The rough equivalent of Python's list comprehension is Array.map:
const myArray = [1, 2, 3]
const transformed = myArray.map((item) => item + 1)
// [2, 3, 4]
But your example is not about an array, but about an Object with keys and values. In Python, this would be a dict, and you'd use a dict comprehension along the lines of {function1(key): function2(value) for key, value in my_dict.items()}.
In JavaScript, you can turn such an object into an array with Object.entries, then perform the map, and finally transform it back into an object using Object.fromEntries:
const myObject = { a: 1, b: 2 }
const transformed = Object.fromEntries(Object.entries(myObject)
.map(([key, value]) => [key + 'x', value + 1]))
// { ax: 2, bx: 3 }
Note that fromEntries is fairly new and you might need to add a polyfill for it.
You can use a code likes this. You must use a function that handle operation on current single item.
const words = ['hello', 'bird', 'table', 'football', 'pipe', 'code'];
const capWords = words.forEach(capitalize);
function capitalize(word, index, arr) {
arr[index] = word[0].toUpperCase() + word.substring(1);
}
console.log(words);
// Expected output:
// ["Hello", "Bird", "Table", "Football", "Pipe", "Code"]
First of all, javascript does NOT support Associative Arrays. If you are used to them in Python, PHP, and other languages you need to do a little workaround in JS to achieve the same functionality.
The most common way to simulate an associative array is using an object.
let testObject = {name: "Color", value: "Red"};
And then you push every object into an array so you end up with something like this:
let testArray = [{name: "Color", value: "Red"}, {name: "Color", value: "Blue"}];
Once you have this array consisting of objects, you can use map function to go through every object in the array and do whatever you want with it.
testArray.map((item, index) => {
console.log("The value of "+index+". item is: "item.value);
})
You can use Array.map() function. It work pretty like Array.forEach() function
const numbers = [1, 2, 3, 4, 5]
let newArray = numbers.map((element) => {
return element * 2
})
console.log(newArray) // excepted : [ 2, 4, 6, 8, 10 ]
It can be reduce using
const numbers = [1, 2, 3, 4, 5]
let newArray = numbers.map(element => element * 2)
console.log(newArray) // excepted : [ 2, 4, 6, 8, 10 ]
For more informations, you can this documentation https://developer.mozilla.org/fr/docs/Web/JavaScript/Reference/Global_Objects/Array/map

Basic Javascript, How can i filter an array by numeric value?

this is my first question on this community and i'm a novice programmer with JavaScript.
I have something like this:
let dog = [["extra small", 2], ["small", 5], ["medium", 7], ["big", 9], ["extra big", 12]];
Taking the data of the previous array, i want to create a new array just with the numeric values, for example:
ages = [2, 5, 7, 9, 12]
I tried to use "filter", but i don't know how to properly use it, also i tried to search some references to make it work but i couldn't.
Thanks in advance (and sorry for my poor english, but i suppose you get the idea).
You can first use Array#map to get just the numbers and then Array#sort to sort the numbers
let dog = [
["extra small", 2],
["small", 5],
["medium", 7],
["big", 9],
["extra big", 12]
];
let ages = dog.map(([size, age]) => age).sort((a, b) => a - b);
console.log(ages);
Here are my thoughts on how to achieve this.
Using Array#Map and Array#filter.
Basically, mapping each element of the array, then checking for the numeric values in the subArray using JavaScript#isNaN() and
returning the numbers.
isNaN() checks if the value type is not a number. !isNaN() reverses that response.
flat() is used to flatten the final result to a single array. Alternatively, you can change map() to flatMap()
// map(), isNaN(), filter(), flat()
let newArr = dog.map((arr) => arr.filter((val) => !isNaN(val))).flat();
console.log(newArr); // [ 2, 5, 7, 9, 12 ]
// flatMap(), isNaN(), filter()
let newArr = dog.flatMap((arr) => arr.filter((val) => !isNaN(val)));
console.log(newArr); // [ 2, 5, 7, 9, 12 ]
Using function.
This is similar to the first, however, instead of using map() we use a Array#forEach to loop through the array.
function getNumeric(array) {
let result = [];
array.forEach((arr) => {
let res = arr.filter((a) => !isNaN(a));
result.push(...(res));
});
return result;
}
let newArr = getNumeric(dog);
console.log(newArr); // [ 2, 5, 7, 9, 12 ]
let dog = [
["extra small", 2],
["small", 5],
["medium", 7],
["big", 9],
["extra big", 12]
];
const newArr = dog.map(item => {
return item[1]
})
console.log(newArr);

Does lodash or vanilla JS have a nice way to flatten an object of arrays into an array?

What I want to do is take an object like
{ SomeKey: [A, B, C],
SomeOtherKey: [D],
AndAnother: [E, F] }
and make it into
[ A, B, C, D, E, F ]
I don't see any nice way in the documentation, but maybe it's hiding in plain sight from me.
If you're on the very latest generation of browsers, you may be able to use Object.values, which does exactly what it sounds like:
const data = {
SomeKey: ['A', 'B', 'C'],
SomeOtherKey: ['D'],
AndAnother: ['E', 'F']
};
const out = [].concat(...Object.values(data));
console.log(out);
If you're on slightly older browsers (back to IE9), Object.keys is still pretty close:
const data = {
SomeKey: ['A', 'B', 'C'],
SomeOtherKey: ['D'],
AndAnother: ['E', 'F']
};
const out = [].concat(...Object.keys(data).map(key => data[key]));
console.log(out);
(concat optimization from vlaz's answer edited in at Oriol's suggestion)
Using vanilla JS
var input = {
SomeKey: ["A", "B", "C"],
SomeOtherKey: ["D"],
AndAnother: ["E", "F"]
};
var outputES5 = Object.keys(input).reduce(function (memo, key) {
return memo.concat(input[key])
}, []);
//Using ES6 fat arrow function
const outputES6 = Object.keys(input).reduce(
(memo, key) => memo.concat(input[key]),
[]
);
//Using Object.values and the spread operator
const outputES6Values = [].concat(...Object.values(input));
console.log("ES5 reduce", outputES5);
console.log("ES6 reduce and fat arrow function", outputES6);
console.log("ES6 Object.values and spread operator", outputES6Values);
Array#reduce()
Object.keys()
Object.values() - NOTE: this is not widely supported as of yet.
Spread syntax ...
Using Lodash
var input = {
SomeKey: ["A", "B", "C"],
SomeOtherKey: ["D"],
AndAnother: ["E", "F"]
};
var output = _.flatMap(input);
console.log(output);
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.16.0/lodash.min.js"></script>
Using _.flatMap() will iterate over all the values of the object since the default iteration function is simply _.identity() and produce a single flattened array of all of them.
It looks like lodash _.flatMap Does this.
https://lodash.com/docs/4.16.0#flatMap
var data = {
SomeKey: ['A', 'B', 'C'],
SomeOtherKey: ['D'],
AndAnother: ['E', 'F']
};
console.log(_.flatMap(data)); //["A", "B", "C", "D", "E", "F"]
Fiddle

Categories