13

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.

Rory McCrossan
  • 331,213
  • 40
  • 305
  • 339
Zlatko Soleniq
  • 390
  • 2
  • 4
  • 14

15 Answers15

37

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"
le_m
  • 19,302
  • 9
  • 64
  • 74
  • 1
    Had to put prototype in String function path to get it to work. Very cool! `String.prototype.concat(...new Set(str))` – Austin Haws Nov 21 '16 at 22:52
  • 1
    @AustinHaws Ah, `String.concat` is one of the [legacy static methods (or “generic methods”)](//developer.mozilla.org/en/docs/Web/JavaScript/Reference/Deprecated_and_obsolete_features#string_2). It used to work in browsers supporting this non-standard extension. `String.prototype.concat.call(...new Set(str))` would be cleaner, though. `String.prototype.concat(...new Set(str))` just happens to work because `String.prototype` (which serves as the `this` value in `String.prototype.concat`) happens to represent an empty string as well. But this fact is less obvious than knowing how `.call` works. – Sebastian Simon Jan 18 '23 at 11:48
24

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. :-)

Sebastian Simon
  • 18,263
  • 7
  • 55
  • 75
Malcolm Holmes
  • 441
  • 4
  • 6
3

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("");
}
Parthasarathy K
  • 121
  • 1
  • 10
2

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;
    });
}
Bergi
  • 630,263
  • 148
  • 957
  • 1,375
2

Using lodash:

_.uniq('aaabbbccc').join(''); // gives 'abc'
Lukasz Wiktor
  • 19,644
  • 5
  • 69
  • 82
1

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));
brian buck
  • 3,284
  • 3
  • 23
  • 24
1

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.

cottonke
  • 131
  • 10
  • He isn't using C#. Its JavaScript. – brian buck Dec 13 '12 at 21:04
  • My comment is still somewhat valid ... I don't have anything handy to run JavaScript in. And I don't think I used anything that is really language dependent. – cottonke Dec 13 '12 at 21:12
  • Mostly -- This line will fail: `bool foundIt = false;` Should be `var foundIt = false;` – brian buck Dec 13 '12 at 21:14
  • it works with var but i have one question what is (!foundIT) and can it be written in a different way – Zlatko Soleniq Dec 13 '12 at 21:18
  • It is just saying that if we didn't find the character in the `unique` string then we need to add it since it is the first time we have come across this particular character. – cottonke Dec 13 '12 at 21:23
1

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"
jayad aadrit
  • 331
  • 3
  • 8
1

<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>
1

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;
    }
Ahmad Adel
  • 136
  • 2
  • 11
1

The one line solution will be to use Set. const chars = [...new Set(s.split(''))];

Delon
  • 741
  • 1
  • 6
  • 14
0

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"));
Sebastian Simon
  • 18,263
  • 7
  • 55
  • 75
jeevandza
  • 3
  • 2
  • Note that the approach using [`filter`](//developer.mozilla.org/en/docs/Web/JavaScript/Reference/Global_Objects/Array/filter) and [`indexOf`](//developer.mozilla.org/en/docs/Web/JavaScript/Reference/Global_Objects/Array/indexOf) has quadratic time complexity, whereas the approach using `Set` has linear time complexity. For larger input sizes (i.e. longer strings), `Set` performs better by far. – Sebastian Simon Jan 18 '23 at 12:01
-1

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;
};
-1
const countUnique = (s1, s2) => new Set(s1 + s2).size

a shorter way based on @le_m answer

-1
let unique=myArray.filter((item,index,array)=>array.indexOf(item)===index)
Suraj Rao
  • 29,388
  • 11
  • 94
  • 103
  • 1
    Please don't post only code as answer, but also provide an explanation what your code does and how it solves the problem of the question. Answers with an explanation are usually more helpful and of better quality, and are more likely to attract upvotes. – Mark Rotteveel Oct 30 '21 at 11:04