Turn a single array into a multidimensional array with javascript - javascript

I came across an exercise that wants me to write a function that splits an array (first argument) into groups the length of size (second argument) and returns them as a multidimensional array. Here is the starter code that is provided.
function chunk(arr, size) {
// Break it up.
return arr;
}
chunk(['a', 'b', 'c', 'd'], 2);
so in this particular case, the returned array should be [[a,b],[c,d]].
I have tried using array.slice, and array.splice, and array.push but I get nothing even close to being the right answer. If anybody can help shed some light on this issue, I would be very appreciative. I have been stuck on this for days and it's getting really frustrating. Thanks.

Not the best code I've ever written but here you go:
function chunk(arr, size) {
mda = []
for (i = 0; i+size < arr.length; i = i + size) {
mda.push(arr.slice(i,i+size));
}
mda.push(arr.slice(i));
return mda
}
chunk(['a', 'b', 'c', 'd'], 2)

Related

Rotate the elements of an array

I am trying to solve a javascript challenge from jshero.net. The challenge is this:
Write a function rotate that rotates the elements of an array. All
elements should be moved one position to the left. The 0th element
should be placed at the end of the array. The rotated array should be
returned. rotate(['a', 'b', 'c']) should return ['b', 'c', 'a'].
All I could come up with was this :
function rotate(a){
let myPush = a.push();
let myShift = a.shift(myPush);
let myFinalS = [myPush, myShift]
return myFinalS
}
But the error message I got was:
rotate(['a', 'b', 'c']) does not return [ 'b', 'c', 'a' ], but [ 3,
'a' ]. Test-Error! Correct the error and re-run the tests!
I feel like I'm missing something really simple but I can't figure out what. Do you guys have other ways to solve this?
function rotate(array){
let firstElement = array.shift();
array.push(firstElement);
return array;
}
To achieve the output you are looking for, first you have to use Array.shift() to remove the first element, then using Array.push() add the element back to the end of the Array, then return the array, the issue is that you used the wrong oder for these steps, also .push() method takes element to be added as argument, here is a working snippet:
function rotate(a){
let myShift = a.shift();
a.push(myShift);
return a;
}
console.log(rotate(['a', 'b', 'c']));
Here I have created a utility where, the input array will not get mutated even after rotating the array as per the requirement.
function rotate(a){
let inputCopy = [...a]
let myShift = inputCopy.shift();
let myFinalS = [...inputCopy, myShift]
return myFinalS
}
console.log(rotate([1,2,3]))
console.log(rotate(["a","b","c"]))
Hope this helps.
function rotate(arr){
let toBeLast = arr[0];
arr.splice(0, 1);
arr.push(toBeLast);
return arr;
}
console.log(rotate(['a', 'b', 'c']));
New to stack overflow. Hope this helps :)
arr.unshift(...arr.splice(arr.indexOf(k)))
Using unshift(), splice() and indexOf(), this is a one line that should help. arr is the array you want to rotate and k the item you want as first element of the array. An example of function could be:
let rotate = function(k, arr) {
arr.unshift(...arr.splice(arr.indexOf(k)))
}
And this are examples of usage:
let array = ['a', 'b', 'c', 'd']
let item = 'c'
rotate(item, array)
console.log(array)
// > Array ["c", "d", "a", "b"]
Finally back to the original array:
rotate('a', array)
console.log(array)
// > Array ["a", "b", "c", "d"]

Order Difference in javascript array of strings

Is there an easy way of getting an order difference of two string arrays?
var A = ['a', 'b'];
var B = ['b', 'a'];
by comparing these two is there an easy way of finding out that they swapped index? i couldnt find anything helpful online and
i dont really want to go the long and hard way about it as the array i am using is quite big. Using dragtable to reorder columns of my datatable and i am constantly pushing data to it so whenever an order changes i want the specific data to go into their designated column that is why i need it, thanks!
You could iterate over one array and compare the index of the current value to the index of same value in the other given array. If both mismatch, you can create map, containing a mismatch matrix for every value which you can use for further computation. See https://jsfiddle.net/f2jL46ke/
const arr1 = ['a', 'b', 'c']
const arr2 = ['b', 'c', 'a']
// I am assuming, that both arrays have an equal length
const differences = arr1.reduce((store, value) => {
const arr1Index = arr1.indexOf(value)
const arr2Index = arr2.indexOf(value)
if(arr1Index !== arr2Index) {
store[value] = [arr1Index, arr2Index]
}
return store
}, {})
console.log(differences)
With that approach you know A) what strings weren't at the same position in the arrays and B) where they are located in both arrays.
You will simply use sort() method
var A = ['a', 'b'];
var B = ['b', 'a'];
B=B.sort();
and B.sort() retutn ['a', 'b'];

JavaScript generator function times out when trying to replicate Python's itertools.combinations

With the help of a couple of answers here I've been able to start learning about generators and develop the following function:
function* icombinations(arr, k) {
function* getCombinations(newArr, shift) {
if (newArr.length === k) {
yield newArr;
}
for (let i = shift; i < arr.length; i++) {
yield* getCombinations([...newArr, arr[i]], i + 1);
}
}
yield* getCombinations([], 0);
return [];
}
Here is a link to repl.it: https://repl.it/E2QW/1
I haven't probably grasped the concept fully since the function above times out for very long inputs as I'm trying to generate all possible combinations first and then yield each one. Would you know how I could refactor the the function so that I don't generate all combinations first?
Here is the description of the challenge that I'm trying to solve:
Write a function called icombinations that should be a generator function with behavior similar to
Python's itertools.combinations. You are given an array arr of unique
items and an integer k.
You should yield each unique combination of elements in arr of length
k with no replacements until there are no possible unique
combinations left, at which point you should terminate the generator
function. Your generator will be called with next(), and in some cases
it will be called until completion.
Additionally It is important that you return combinations in the same
order as the original array arr. (see the example below)....
For example:
given an array of unique elements example_arr and an integer
example_k:
where example_arr = ['a', 'b', 'c', 'd'] and example_k = 2;
calling the next() method of the iterator should return [ 'a', 'b' ].
if we were to call next() again we should get [ 'a', 'c' ] and so
on...
so that if we got all values yielded by the generator we would have
the following:
[ 'a', 'b' ] [ 'a', 'c' ] [ 'a', 'd' ] [ 'b', 'c' ] [ 'b', 'd' ] [
'c', 'd' ] again, notice the order of the above, as you will need to
replicate it in your solution.
Some more things to consider:
If your solution is timing out, it may be because you tried to
generate all possible combinations first and then yield each one.
This defeats the point of a generator. Some of input values will be
large.
Values in arr will always be unique but they may be of different types
(i.e. strings, integers, other objects).
The only cases in which you would not be able to produce combinations
is that in which arr is null or empty or has a length less than k. In
any of those situations you should return an empty array.
You might be able to get better suggestions on Code Review, but one improvement you can try is to prune some of the "dead-end" recursive paths. Since you know that each result must be length k, you should only recurse when you have enough elements left in the source array to actually complete a k-subset.
function* icombinations(arr, k) {
function* getCombinations(newArr, shift) {
if (newArr.length === k) {
yield newArr;
}
// if what's available is >= what's needed
else if (arr.length - shift >= k - newArr.length) {
for (let i = shift; i < arr.length; i++) {
yield* getCombinations([...newArr, arr[i]], i + 1);
}
}
}
yield* getCombinations([], 0);
return [];
}
But without your test cases or limits on arr.length and k, we can't know if this is good enough. You mentioned that arr.length could be 50, which means a maximum of 126,410,606,437,752 subsets when k is 25. No algorithm no matter how efficient will complete that in any reasonable amount of time. Even when k is 5 (or equivalently, 45), you're looking at 2,118,760 combinations.
Another thing you could try is to pre-allocate the subset array (newArr) outside of the inner function and then update the array in-place prior to each recursive invocation. This avoids the need to copy newArr each time you want to append a value to it, but you will still need to yield a copy of newArr in your base case. This, however, is more of a micro-optimization compared to the branch-pruning. Try the pruning first by itself to see how much of improvement each change makes.
Finally, you could also switch to an iterative implementation and see if that works.

How to get the even and odd entries from an array with Ramda

I have the following:
var isEven = function (n) { return n % 2 === 0; }
var isOdd = function (n) { return n % 2 !== 0; }
var indexedList = function(fn, list) {
var array = [];
for (var i = 0; i < list.length; i++) {
if (fn(i)) {
array.push(list[i]);
}
}
return array;
}
Is there a Ramda equivalent of IndexedList so I can have an array of just the even index based elements and an array of odd based index elements.
Ramda's list-based functions by default do not deal with indices. This, in part, is because many of them are more generic and also work with other data structures where indices don't make sense. But there is a standard mechanism for altering functions so that they do pass the indices of your lists along: addIndex.
So my first thought on this is to first of all, take your isEven and extend it to
var indexEven = (val, idx) => isEven(idx);
Then you can use addIndex with filter and reject like this:
R.addIndex(R.filter)(indexEven, ['a', 'b', 'c', 'd', 'e']);
//=> ['a', 'c', 'e']
R.addIndex(R.reject)(indexEven, ['a', 'b', 'c', 'd', 'e']);
//=> ['b', 'd']
Or if you want them both at once, you can use it with partition like this:
R.addIndex(R.partition)(indexEven, ['a', 'b', 'c', 'd', 'e']);
//=> [["a", "c", "e"], ["b", "d"]]
You can see this in action, if you like, on the Ramda REPL.
If the list length is even, I would go with
R.pluck(0, R.splitEvery(2, ['a','b','c']))
The disadvantage of this is that it will give undefined as a last element, when list length is odd and we want to select with offset 1 ( R.pluck(1) ). The advantage is that you can easily select every nth with any offset while offset < n.
If you can't live with this undefined than there is another solution that I find more satisfying than accepted answer, as it doesn't require defining a custom function. It won't partition it nicely though, as the accepted answer does.
For even:
R.chain(R.head, R.splitEvery(2, ['a','b','c','d']))
For odd:
R.chain(R.last, R.splitEvery(2, ['a','b','c','d']))
As of Ramda 0.25.0, the accepted solution will not work. Use this:
const splitEvenOdd = R.compose(R.values, R.addIndex(R.groupBy)((val,idx) => idx % 2))
splitEvenOdd(['a','b','c','d','e'])
// => [ [ 'a', 'c', 'e' ], [ 'b', 'd' ] ]

Rename multiple same occurrences in array

I have an array of titles (sentences). Some of these titles repeat in this whole array, so for example my array is (shortened titles for clarity):
var arr = ['a','b', 'c', 'a', 'f', 'r', 'b', 'a'];
As you can see some values repeat more than once. I need to rename multiple occurrences by appending the counter (starting from 1) to the first matching occurrence.
So in the end I must have:
'a', 'a1', 'a2', 'b', 'b1'
which means I need to have counter stored for every of the repeating occurrence.
How could I write this in javascript/jquery?
Here's some pseudocode, wherein tally is a title-count mapping (e.g. {title:0}):
for (var i = 0; i < arr.length; i++) {
if (arr.indexOf(arr[i]) != i) {
tally[arr[i]]++;
arr[i] = arr[i] + tally[arr[i]];
}
}
Language agnostic algorithm
Add the elements of array to map so that no duplicate elements would be present and initialize it to 0.
Iterate through array
Check if the elemnt is present in map
if present then
map[element]++;
element+value of element at map+1;
else element
Example:
var arr = ['a','b', 'c', 'a', 'f', 'r', 'b', 'a'];
//initialize the map
map m
m[a]=0; m[b]=0; m[c]=0; m[f]=0; m[r]=0;
for(index=0 to size of array){
if(m[arr[index]]){
m[arr[index]]++;
write arr[index] with m[arr[index]];
}else{
write arr[index];
}
}
You could use maps as mentioned here How to create a simple map using JavaScript/JQuery and then I think everything is almost same.

Categories

Resources