is splice 3rd parameter iaccepting any value? - javascript

I can't figure out why newArr is not changing. Seems like my splice function isnt accepting "first13[index]" as argument. Though, when i change "index" to a fixed value, everything worck. I indeed consoleloged index, and it shows correct values as integer. Im really confused here. Any tips?
function rot13(str) {
let first13 = ['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm'];
let second13 = ['n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z'];
let newArr = str.toLowerCase().split('');
let index = 0;
for (let i=0; i<newArr.length; i++) {
if(first13.indexOf(newArr[i]) != -1) {
index = first13.indexOf(newArr[i]);
newArr.splice(i, 1, first13[index]);
console.log(newArr);
}
}
}
rot13("EBG13 rknzcyr.") // "ROT13 example.";

The code's working fine.
There is a mistake in your logic.
You are just replacing the element with the same.
For example you are replacing E with first13(index) which is E.
May be change first13[index] to second13[index] if you want to replace it with +13 characters.
EDIT: The above change must be made for parameter of splice() method.

Everything is working exactly as it's coded as...
Dry running your code:
iteration 1:
index=0
i=0
if( first13.indexOf("e") != -1 ) //true
{
index = first13.indexOf("e") //index = 4
newArr.splice(0,1,first13[4]) //at 0th index remove one element and add first13[4] therefore newArr[0] becomes "e" from "e" (basically remains same)
console.log(newArray) . //printing the array which is same as before.
}
iteration 2:
index=4 //from last iteration
i=1
if( first13.indexOf("b") != -1 ) //true
{
index = first13.indexOf("e") //index = 1
newArr.splice(1,1,first13[1]) //at 1st index remove one element and add first13[1] therefore newArr[1] becomes "b" from "b" (basically remains same)
console.log(newArray) //printing the array which is same as before.
}
After every iteration the array is same since you're replacing elements with same element, as seen above. Re write the logic. You haven't coded what you wanted to do...

With the current setup, the code is just replacing letters in newArr with the same letter from first13.
When the code runs through the first time,
index = first13.indexOf(newArr[i]);
is setting index = 4, then
newArr.splice(i, 1, first13[index]);
is taking the letter at first13[4], 'e' in this case, and replacing newArr[0], which also happens to already be 'e'.
As Raj Datta Manohar suggested above, change the last property in your splice method to second13[index] and you should get something closer to what you're looking for.

Everyone here has already answered how to correct the logic in your code. Below is just another way to approach the problem that might help in reading the logic because there's a little less going on.
function rot13(str) {
let input = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz';
let output = 'NOPQRSTUVWXYZABCDEFGHIJKLMnopqrstuvwxyzabcdefghijklm';
let index = (x) => input.indexOf(x);
let translate = (x) => index(x) > -1 ? output[index(x)] : x;
console.log(str.split('').map(translate).join(''));
}
rot13("EBG13 rknzcyr."); // ROT13 example.

Related

Insert an element in array after a specific value and only if this value respect a condition || Javascript

I looked for a solution in the many other requests I could consult on the site but either it doesn't really correspond to what I want to do or the language is different.
Here is my problem:
I would like to add a particular value in an array if the condition is valid.
For example:
If a string is entered (e.g. "Hello World"), I would like the letter 'p' to be inserted after the letter 'o'. It would then give the output of the function: "Hellop Woprld".
Here is my current approach :
function transform(input) {
const inputArray = input.split('');
const codeLetter = 'p';
inputArray.map((inputEl, i) => {
if (inputEl === 'o') {
inputArray.splice(inputEl[i+1], 0, codeLetter)
} else {
return inputArray;
}
});
return inputArray;
}
console.log(transform("Hello World"));
And here is the resulting output:
[
'p', 'p', 'p', 'p', 'p',
'p', 'p', 'H', 'e', 'l',
'l', 'o', ' ', 'W', 'o',
'r', 'l', 'd'
]
Two problems are open to me:
My approach concerning the iteration of the letter 'p' is wrong
the elements are added at the beginning of the table and not after the letter 'o'.
I'm always looking but I can't find the right approach.
Does anyone have any idea what soultion is?
Thank you in advance
Simpler:
const codeLetter = "p";
const specialLetter = "o";
const transform = input => input.split(specialLetter).join(specialLetter+codeLetter)
console.log(transform("Hello World"));

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"]

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.

Remove array elements and add them back to where they were

I am trying to remove elements from arrays while remembering their position and add them back later. So far I have this piece of code:
var my_array = ['A', 'B', 'C', 'D', 'E'];
var removed_elements = [];
// Assuming letter provided exists in my_array
function remove_element(letter) {
for (var index in my_array) {
if (my_array[index] == letter) {
break;
}
}
var removed_element = {
index: index,
letter: letter
}
removed_elements.push(removed_element);
my_array.splice(index,1);
}
// Assuming letter provided exists in removed_elements
function add_element(letter) {
for (var index in removed_elements) {
console.log('test');
if (removed_elements[index].letter == letter) {
console.log(removed_elements[index]);
break;
}
}
my_array.splice(removed_elements[index].index,0,removed_elements[index].letter);
}
It works fine as long as I remove 1 element at a time and add it back before removing another one. However, when I start removing several elements consecutively, the index saved for removed elements (not first one, but subsequent ones) becomes relative to the state of my_array at the time of removal, and not absolute to my_array's initial state, which can cause problems.
For instance if you remove 'B' and 'D' and add 'D' and 'B', you end up with ['A', 'B', 'C', 'E', 'D'] instead of ['A', 'B', 'C', 'D', 'E'].
Here is a jsfiddle showing what the problem is
What modifications should I change for my_array to end up in its initial state no matter of many elements I remove or add and how?
I thought about storing information about which elements surround the removed element at the time of removal and use that as extra info when adding back but wondering if there is a better way.
I wouldn't actually remove them at all:
var my_array = ['A', 'B', 'C', 'D', 'E'];
var removed = [];
function remove_element(letter) {
var i = my_array.indexOf(letter);
if(i > -1) {
removed.push(i);
}
}
function add_element(letter) {
var i = my_array.indexOf(letter);
if(i > -1) {
removed.splice(removed.indexOf(i), 1);
}
}
function get_array() {
return my_array.filter(function(x, i) {
return removed.indexOf(i) === -1;
});
}

Categories

Resources