Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 5 years ago.
Improve this question
Got string, need to delete same words from there.
Here is my code. I tried to split string into array and then sort but it didn't work. It didn't even go through my if. I would like to hear your advice and maybe working code :)
var str = "I wont go anywhere as soon as I wont go there";
var array = str.split(" ");
document.getElementsByTagName('p')[0].innerHTML = str;
document.getElementsByTagName('p')[1].innerHTML = array;
document.getElementsByTagName('button')[0].onclick = function () {
for (var i = 0; i < array.length; i++) {
if (array[i] == array[i + 1]) {
array.splice(i, 1);
}
}
document.getElementsByTagName('p')[2].innerHTML = array;
}
If you like one-lines try this
var reducedString = array.reduce(function(out, s) {
return out.indexOf(s) == -1 ? out + ' ' + s : out;
},'').substring(1);
or in ES6
var reducedString = array.reduce( (out, s) => out.indexOf(s) == -1 ? out + ' ' + s : out);
Your problem is that you don't check every array element with every other array element.
Your code:
for (var i = 0; i < array.length; i++) {
if (array[i] == array[i + 1]) {
array.splice(i, 1);
}
}
Just checks array elements in sequence.
Try:
for (var i = 0; i < array.length; i++) {
for(var j = 0; j < array.length; j++){
if (array[i] == array[j] && i != j) {
array.splice(i, 1);
}
}
}
You can use an ES6 Set with the spread syntax after splitting the sentance:
const str = "I wont go anywhere as soon as I wont go there";
const unique = [...new Set(str.split(' '))].join(' ');
console.log(unique);
In ES5 you can use Array#reduce with a dictionary object.
var str = "I wont go anywhere as soon as I wont go there";
var dict = Object.create(null); // creates an empty object, without inherited properties and methods
var unique = str.split(' ').reduce(function(arr, w) {
if(!dict[w]) {
arr.push(w);
dict[w] = true;
}
return arr;
}, []).join(' ');
console.log(unique);
You can just replace the substring you are searching for
var ret = "data-123".replace('data-','');
console.log(ret);
Related
I would like to duplicate every single letter in my string and uppercasing the first letter.
Like this case:
accum("abcd") -> "A-Bb-Ccc-Dddd".
However, it alters the first letter of the string. I think I should add another iterator called "j". But I don't know how to do it.
Precisely, the only task remaining in my code is to move on to the next letter while saving the changes made for the first letter.
function accum(s) {
var i = 0;
while ( i<s.length){
for (var j =i; j<i ; j++) {
s=s[j].toUpperCase()+s[j].repeat(j)+"-";
i+=1;
}
}
return s.slice(0,s.length-1);
}
Try this:
function accum(s) {
let newString = '';
for(let i = 0; i < s.length; i++) {
newString += s[i].toUpperCase() + s[i].repeat(i) + "-";
}
return newString.slice(0, newString.length - 1);
}
I guess you don't need two repetition loops at all (either you can keep the for or the while, i kept the for).
Your fundamental mistake was in this line: s=s[j].toUpperCase()+s[j].repeat(j)+"-"; where you replaced s with the new string instead of concatenating it (s += instead of s = ). Which would be wrong anyway because you are replacing the original string. You need another empty string to keep the changes separated from the original one.
Do this:
function accum(s) {
accumStr = '';
for (var i=0; i < s.length; i++) {
for (var j = 0; j <= i; j++) {
accumStr += j !== 0 ? s[i] : s[i].toUpperCase();
}
}
return accumStr;
}
console.log(accum('abcd')) //ABbCccDddd
Try this:
function accum(s) {
let strArr = s.split('');
let res = [];
for (let i in strArr) {
res.push(strArr[i].repeat(parseInt(i)+1));
res[i] = res[i].charAt(0).toUpperCase() + res[i].slice(1);
}
return res.join('-');
}
console.log(accum('abcd'))
try to use reduce method
const accum = (str) => {
return [...str].reduce(
(acc, item, index, arr) =>
acc +
item.toUpperCase() +
item.repeat(index) +
(index < arr.length - 1 ? "-" : ""),
""
);
};
console.log(accum("abcd")); //A-Bb-Ccc-Dddd
Okay so palindrome is a word that is the same spelled backwards. What if we want to take a phrase that is also the same backwards? So kook is one. race car is another one.
So I made one that doesn't account for spaces.
function isPal(string){
var l = string.length;
for (var i = 0; i < (l/2); ++i) {
if (string.charAt(i) != string.charAt(l - i - 1)){
return false;
}
}
return true;
}
This one works fine for words.
Now I'm thinking, push the string into an array, and split up each character into it's own string, then remove any spaces, and then run if (string.charAt(i) != string.charAt(string.length - i - 1)). So here's what I wrote but failed at..
function isPalindrome(string){
var arr = [];
arr.push(string.split(''));
for (i = 0; i < arr.length; i++){
if (arr[i] === ' '){
arr.splice(i, 1);
if I return arr, it still gives me the string with the space in it. How do I accomplish this? Thanks!
EDIT: Used the solution but still getting false on 'race car'
Here's what I got:
function isPalindrome(string){
var arr = string.split('');
for (i = 0; i < arr.length; i++){
if (arr[i] === ' '){
arr.splice(i, 1);
} else if (arr[i] != arr[arr.length - i - 1]){
return false;
}
}
return true;
}
where's my error?
Your problem is in the following line:
arr.push(string.split(''));
string.split('') returns an array. So, arr is actually an array with one entry it in (another array that contains your characters). Replace:
var arr = [];
arr.push(string.split(''));
with
var arr = string.split('');
and it should work as expected
Just check check the string without spaces:
function isPal(string){
string = string.split(" ").join(""); // remove all spaces
var l = string.length;
for (var i = 0; i < (l/2); ++i) {
if (string.charAt(i) != string.charAt(l - i - 1)){
return false;
}
}
return true;
}
isPal("a man a plan a canal panama"); // true
It seems much easier to just split into an array, reverse and join again to check if a word is a palindrome. If you want to ignore spaces, just remove all instances of spaces:
let word = 'race car';
let isPalindrome = (word) => {
let nospaces = word.replace(/\s/g, '');
return [...nospaces].reverse().join('') === nospaces;
}
Or non-es6:
var word = 'race car';
var isPalindrome = function(word) {
var nospaces = word.replace(/\s/g, '');
return nospaces.split('').reverse().join('') === nospaces;
}
I'e been trying to write one and it's getting messy!
Suppose I have two strings textStart, textTarget and I want to keep track of the characters I would need to add and remove from textStart in order to product textTarget.
For instance, if textStart = "dude" and textTarget = "deck", then characters that would need to be added would be 'c' and 'k' and the characters that would need to be substracted would be the 'u' and one of the 'd's.
I'm thinking that I first need to create maps that represent the number of each character in textStart and textTarget.
So I wrote this:
var startChars = {};
for (var k = 0, n = textStart.length; k < n; ++k)
{
if (textStart[k] in startChars)
++startChars[textStart[k]];
else
startChars[textStart[k]] = 1;
}
var targetChars = {};
for (var k = 0, n = textTarget.length; k < n; ++k)
{
if (textTarget[k] in startChars)
++targetChars[textTarget[k]];
else
map1[targetChars[k]] = 1;
}
Which would give me
startChars['d']=2,
startChars['u']=1,
startChars['e']=1
and
targetChars['d']=1,
targetChars['e']=1,
targetChars['c']=1,
targetChars['k']=1
Then I can make create maps needAdded and needRemoved that look at the difference in the above two maps:
var needAdded = {};
var needRemoved = {};
I'm not sure how to fill those maps as intended, because I don't know how to iterate through the keys of a map using JavaScript. I somehow need to end up with
needAdded['c']=1,
needAdded['k']=1,
needRemoved['u']=1,
needRemoved['d']=1
That's where you guys come in and help me.
I hope I've done a good job describing what I'm trying to do and how I've tried to do it so far. My programming intuition tells me that I'm writing too many lines of code and that I need to consult StackOverflow for help. Any way to do this elegantly without JQuery or Regex? I know someone's going to come in this thread and write a 1-line Regex solution or something like that.
var s = 'dude',
t = 'deck',
finalOutput = '';
for (var i = 0; i < s.length; i++){
if ( typeof t[i] != 'undefined' ){
if ( s[i] != t[i] ){
console.log(s[i] + ' changed to ' + t[i]);
s[i] = t[i];
finalOutput += t[i];
} else{
finalOutput += s[i];
}
}
}
console.log('FINAL: ' + finalOutput);
Here's a jsfiddle I just spent way too much time on... hopefully it makes sense :)
var textStart = 'dude';
var textTarget = 'deck';
var startChars = {};
for (var k = 0, n = textStart.length; k < n; ++k)
{
if (textStart[k] in startChars)
++startChars[textStart[k]];
else
startChars[textStart[k]] = 1;
}
var targetChars = {};
for (var k = 0, n = textTarget.length; k < n; ++k)
{
if (textTarget[k] in targetChars)
++targetChars[textTarget[k]];
else
targetChars[textTarget[k]] = 1;
}
console.log('start: ' + JSON.stringify(startChars));
console.log('target: ' + JSON.stringify(targetChars));
var needAdded = {};
var needRemoved = {};
for (var c in startChars) {
// If target does not contain letter, remove all, otherwise remove excess
if (targetChars[c] > 0) {
if (startChars[c] > targetChars[c])
needRemoved[c] = startChars[c] - targetChars[c];
else if (startChars[c] < targetChars[c])
needAdded[c] = targetChars[c] - startChars[c];
} else {
needRemoved[c] = startChars[c];
}
}
for (var c in targetChars) {
// If start does not contain letter, add all, otherwise add excess
if (startChars[c] > 0) {
if (startChars[c] > targetChars[c])
needRemoved[c] = startChars[c] - targetChars[c];
else if (startChars[c] < targetChars[c])
needAdded[c] = targetChars[c] - startChars[c];
} else {
needAdded[c] = targetChars[c];
}
}
console.log('needAdded: ' + JSON.stringify(needAdded));
console.log('needRemoved: ' + JSON.stringify(needRemoved));
The output is as follows:
start: {"d":2,"u":1,"e":1}
target: {"d":1,"e":1,"c":1,"k":1}
needAdded: {"c":1,"k":1}
needRemoved: {"d":1,"u":1}
Ok, also too much time on this:
var textStart = "dude";
var textTarget = "duck";
var map = {};
MapCharacters(textStart, map, 1);
MapCharacters(textTarget, map, -1);
console.log(map);
var toDelete = [];
var toAdd = [];
for (var prop in map) {
if (map.hasOwnProperty(prop)) {
while (map[prop] > 0) {
toDelete.push(prop);
map[prop]--;
}
while (map[prop] < 0) {
toAdd.push(prop);
map[prop]++;
}
}
}
console.log(toDelete);
console.log(toAdd);
function MapCharacters(string, map, add) {
for (var k = 0, n = string.length; k < n; ++k) {
if (string[k] in map) {
map[string[k]] += add;
} else {
map[string[k]] = add;
}
}
}
http://jsfiddle.net/nSV2J/1/
It could probably be done more efficiently, but as I said - too much time!
I realized that the best way to do this is not to make two maps, but just one. In the first case you increment the count for each letter and in the second case you decrease it. Now it's easy to find which ones need to be removed (the ones that end up > 0) and which ones need to be added (the ones that end up < 0)
Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 9 years ago.
Improve this question
Trying to write a simple function to take a string as input, then shift each character over once alphabetically. (a -> b) (f -> g) (z -> a). My function so far is broken. I'm sure there are better ways to go about this, but if someone would be willing to troubleshoot my function that would be awesome. :)
function translate(str) {
var alphabet = ['a','b','c','d','e','f','g','h','i','j','k',
'l','m','n','o','p','q','r','s','t','u','v','w','x','y','z'];
str.toLowerCase();
var i = 0;
var j;
//edit: deleted str = ""
while (i < str.length) {
for (j = 0; j < alphabet.length; j++) {
if (str[i] == alphabet[alphabet.length - 1]) { //changed data type
str += alphabet[0]
j=0;
} else if (str[i] == alphabet[j]) {
str += alphabet[j+1]; //fixed this
j=0;
} else {
i++;
}
}
}
return str;
You could also use charCodeAt and fromCharCode to realize your shifting. I might be a little bit more convienent:
function translate(str) {
res = [];
for (var i = 0; i < str.length; i++) {
var ch = str.charCodeAt(i);
//65 => A
//90 => Z
//97 => a
//122 => z
//if ch betweet A and Z or between a and z
if ((ch >= 65 && ch <= 90) || (ch >= 97 && ch <= 122)) {
//if z or Z transform to a or A respectively
if (ch === 90 || ch === 122) ch -= 25;
//else increase by one
else ch += 1;
}
res.push(ch);
}
return = String.fromCharCode.apply(this, res);
}
Both methods use unicode representation of the string. Essentially, you transform the single characters into numbers, increase those numbers by one and transform it back to a letter. Here is a unicode table that shows the value of each letter: http://www.utf8-chartable.de/unicode-utf8-table.pl?utf8=dec
Your logic is a little flawed. Just iterate through the string and use the indexOf method along with the modulo operator:
var index = alphabet.indexOf(char.toLowerCase());
if (index === -1) {
// char isn't in the alphabet, so you should skip it
} else {
var newChar = alphabet[(index + 1) % alphabet.length];
}
(index + 1) adds 1 to the index, which selects the next letter, and % alphabet.length makes it wrap around to the beginning in case of z.
Here's one way to do it:
function translate(str) {
var newStr = "";
var alphabet = ['a','b','c','d','e','f','g','h','i','j','k','l','m','n','o','p','q','r','s','t','u','v','w','x','y','z'];
for (var i = 0; i < str.length; i++) {
var currentLetter = str.substring(i, i+1);
var newLetter = alphabet[(alphabet.indexOf(currentLetter.toLowerCase()) + 1) % alphabet.length];
// preserve the case of the letter
newStr += (currentLetter === currentLetter.toUpperCase()) ? newLetter.toUpperCase() : newLetter;
}
return newStr;
}
The general idea is to loop through each character, find its position in the alphabet array, and add its successor to the new string.
You'll have to add more logic if you need it to handle strings containing symbols, numbers, etc.
I can see a few problems here.
var str = "";. str is the variable you are sending as a parameter, so you reset it with this statement.
if (str[i] == alphabet.length - 1). str[i] and alphabet.length - 1 are not the same data type, so this statement is probably not doing what you think it should. Maybe you should have alphabet[alphabet.length - 1] instead.
else if (str[i] == alphabet[j]) { str += alphabet[j]; //... }. This would add the same letter onto your result string if you didn't reset str like in #1. You should have something like alphabet[(j+1) % alphabet.size] instead.
Also, you should use charAt(i) for getting characters in a string, not subscripts ([]), and you don't have to call j=0 at the end of your for loops, since you already say j=0 in the loop.
I have a string with repeated letters. I want letters that are repeated more than once to show only once.
Example input: aaabbbccc
Expected output: abc
I've tried to create the code myself, but so far my function has the following problems:
if the letter doesn't repeat, it's not shown (it should be)
if it's repeated once, it's show only once (i.e. aa shows a - correct)
if it's repeated twice, shows all (i.e. aaa shows aaa - should be a)
if it's repeated 3 times, it shows 6 (if aaaa it shows aaaaaa - should be a)
function unique_char(string) {
var unique = '';
var count = 0;
for (var i = 0; i < string.length; i++) {
for (var j = i+1; j < string.length; j++) {
if (string[i] == string[j]) {
count++;
unique += string[i];
}
}
}
return unique;
}
document.write(unique_char('aaabbbccc'));
The function must be with loop inside a loop; that's why the second for is inside the first.
Fill a Set with the characters and concatenate its unique entries:
function unique(str) {
return String.prototype.concat.call(...new Set(str));
}
console.log(unique('abc')); // "abc"
console.log(unique('abcabc')); // "abc"
Convert it to an array first, then use Josh Mc’s answer at How to get unique values in an array, and rejoin, like so:
var nonUnique = "ababdefegg";
var unique = Array.from(nonUnique).filter(function(item, i, ar){ return ar.indexOf(item) === i; }).join('');
All in one line. :-)
Too late may be but still my version of answer to this post:
function extractUniqCharacters(str){
var temp = {};
for(var oindex=0;oindex<str.length;oindex++){
temp[str.charAt(oindex)] = 0; //Assign any value
}
return Object.keys(temp).join("");
}
You can use a regular expression with a custom replacement function:
function unique_char(string) {
return string.replace(/(.)\1*/g, function(sequence, char) {
if (sequence.length == 1) // if the letter doesn't repeat
return ""; // its not shown
if (sequence.length == 2) // if its repeated once
return char; // its show only once (if aa shows a)
if (sequence.length == 3) // if its repeated twice
return sequence; // shows all(if aaa shows aaa)
if (sequence.length == 4) // if its repeated 3 times
return Array(7).join(char); // it shows 6( if aaaa shows aaaaaa)
// else ???
return sequence;
});
}
Using lodash:
_.uniq('aaabbbccc').join(''); // gives 'abc'
Per the actual question: "if the letter doesn't repeat its not shown"
function unique_char(str)
{
var obj = new Object();
for (var i = 0; i < str.length; i++)
{
var chr = str[i];
if (chr in obj)
{
obj[chr] += 1;
}
else
{
obj[chr] = 1;
}
}
var multiples = [];
for (key in obj)
{
// Remove this test if you just want unique chars
// But still keep the multiples.push(key)
if (obj[key] > 1)
{
multiples.push(key);
}
}
return multiples.join("");
}
var str = "aaabbbccc";
document.write(unique_char(str));
Your problem is that you are adding to unique every time you find the character in string. Really you should probably do something like this (since you specified the answer must be a nested for loop):
function unique_char(string){
var str_length=string.length;
var unique='';
for(var i=0; i<str_length; i++){
var foundIt = false;
for(var j=0; j<unique.length; j++){
if(string[i]==unique[j]){
foundIt = true;
break;
}
}
if(!foundIt){
unique+=string[i];
}
}
return unique;
}
document.write( unique_char('aaabbbccc'))
In this we only add the character found in string to unique if it isn't already there. This is really not an efficient way to do this at all ... but based on your requirements it should work.
I can't run this since I don't have anything handy to run JavaScript in ... but the theory in this method should work.
Try this if duplicate characters have to be displayed once, i.e.,
for i/p: aaabbbccc o/p: abc
var str="aaabbbccc";
Array.prototype.map.call(str,
(obj,i)=>{
if(str.indexOf(obj,i+1)==-1 ){
return obj;
}
}
).join("");
//output: "abc"
And try this if only unique characters(String Bombarding Algo) have to be displayed, add another "and" condition to remove the characters which came more than once and display only unique characters, i.e.,
for i/p: aabbbkaha o/p: kh
var str="aabbbkaha";
Array.prototype.map.call(str,
(obj,i)=>{
if(str.indexOf(obj,i+1)==-1 && str.lastIndexOf(obj,i-1)==-1){ // another and condition
return obj;
}
}
).join("");
//output: "kh"
<script>
uniqueString = "";
alert("Displays the number of a specific character in user entered string and then finds the number of unique characters:");
function countChar(testString, lookFor) {
var charCounter = 0;
document.write("Looking at this string:<br>");
for (pos = 0; pos < testString.length; pos++) {
if (testString.charAt(pos) == lookFor) {
charCounter += 1;
document.write("<B>" + lookFor + "</B>");
} else
document.write(testString.charAt(pos));
}
document.write("<br><br>");
return charCounter;
}
function findNumberOfUniqueChar(testString) {
var numChar = 0,
uniqueChar = 0;
for (pos = 0; pos < testString.length; pos++) {
var newLookFor = "";
for (pos2 = 0; pos2 <= pos; pos2++) {
if (testString.charAt(pos) == testString.charAt(pos2)) {
numChar += 1;
}
}
if (numChar == 1) {
uniqueChar += 1;
uniqueString = uniqueString + " " + testString.charAt(pos)
}
numChar = 0;
}
return uniqueChar;
}
var testString = prompt("Give me a string of characters to check", "");
var lookFor = "startvalue";
while (lookFor.length > 1) {
if (lookFor != "startvalue")
alert("Please select only one character");
lookFor = prompt(testString + "\n\nWhat should character should I look for?", "");
}
document.write("I found " + countChar(testString, lookFor) + " of the<b> " + lookFor + "</B> character");
document.write("<br><br>I counted the following " + findNumberOfUniqueChar(testString) + " unique character(s):");
document.write("<br>" + uniqueString)
</script>
Here is the simplest function to do that
function remove(text)
{
var unique= "";
for(var i = 0; i < text.length; i++)
{
if(unique.indexOf(text.charAt(i)) < 0)
{
unique += text.charAt(i);
}
}
return unique;
}
The one line solution will be to use Set. const chars = [...new Set(s.split(''))];
If you want to return values in an array, you can use this function below.
const getUniqueChar = (str) => Array.from(str)
.filter((item, index, arr) => arr.slice(index + 1).indexOf(item) === -1);
console.log(getUniqueChar("aaabbbccc"));
Alternatively, you can use the Set constructor.
const getUniqueChar = (str) => new Set(str);
console.log(getUniqueChar("aaabbbccc"));
Here is the simplest function to do that pt. 2
const showUniqChars = (text) => {
let uniqChars = "";
for (const char of text) {
if (!uniqChars.includes(char))
uniqChars += char;
}
return uniqChars;
};
const countUnique = (s1, s2) => new Set(s1 + s2).size
a shorter way based on #le_m answer
let unique=myArray.filter((item,index,array)=>array.indexOf(item)===index)