Following were an output from an array returned by following function:
$scope.variantOptions = $scope.variantLists.join(", ");
medium,small,medium,small,small
How can I sort the result, so it represent the output as:
medium x 2,small x 3
EDIT
addCount function:
$scope.addCount = function($index){
$scope.counter = 1;
if($scope.activity['variant'][$index]['count'] != undefined ){
$scope.counter = parseInt($scope.activity['variant'][$index]["count"]) +1;
$scope.variantLists.push($scope.activity['variant'][$index]['variant_dtl_name']);
}
$scope.activity['variant'][$index]["count"] = $scope.counter;
console.log(arraySimplify($scope.variantLists));
};
Thanks!
pass your '$scope.variantLists' arry into this function it will give you the expected result.
function arraySimplify(arr){
arr.sort();
var rslt = [], element =arr[0] ,count = 0 ;
if(arr.length === 0) return; //exit for empty array
for(var i = 0; i < arr.length; i++){
//count the occurences
if(element !== arr[i]){
rslt.push(element + ' x ' + count);
count =1;
element = arr[i];
}
else{
count++;
}
}
rslt.push(element + ' x ' + count);
return rslt.join(', ');
}
Your code is working:
for (var i = 0;i < $scope.variantLists.length;i++) {
obj[arr[i]] = (obj[arr[i]] || 0) + 1;
}
Gives you an object:
obj = {medium: 2, small: 3}
To see it without having to go into the console, you can just alert the object after the 'for' loop:
alert(obj);
To get the EXACT string you want:
var string = "";
for (var key in obj) {
if (obj.hasOwnProperty(key)) {
var count = validation_messages[key];
string += key + " x " + count;
}
}
Although it may look like an entry in Code Golf but this is one of the rare times when Array.reduce makes sense.
var r = a.sort().reduce(
function(A,i){
A.set(i, (!A.get(i))?1:A.get(i)+1);
return A;
},new Map());
Which makes basically what Jon Stevens proposed but in a more modern and highly illegible way. I used a Map because the order in a normal Object dictionary is not guaranteed in a forEach loop. Here r.forEach(function(v,k,m){console.log(k + ":" + v);}) gets printed in the order of insertion.
Related
The code below should reverse all the characters in a sentence, but it is unable to do so. This is child's play to me but at this moment it's not compiling. Can anyone figure out the issue?
Let's say:
"Smart geeks are fast coders".
The below code should reverse the above string as follows:
"trams skeeg era tsaf sredoc"
function solution(S){
var result = false;
if(S.length === 1){
result = S;
}
if(S.length > 1 && S.length < 100){
var wordsArray = S.split(" "),
wordsCount = wordsAray.length,
reverseWordsString = '';
for(var i = 0; i< wordsCount; i++){
if(i > 0){
reverseWordsString = reverseWordsString + ' ';
}
reverseWordsString = reverseWordsString + wordsAray[i].split("").reverse().join("");
}
result = reverseWordsString;
}
return result;
}
This should give you the result you're looking for.
function reverseWords(s) {
return s.replace(/[a-z]+/ig, function(w){return w.split('').reverse().join('')});
}
function reverseWords(s) {
var arr = s.split(" ");
s = '';
for(i = 0; i < arr.length; i++) {
s += arr[i].split('').reverse().join('').toLowerCase() + " ";
}
return s;
}
Wouldn't that do the job for you? Basically it just converts the string into an array, by splitting it on space. Then it loops over the array, adds every string reversed to a new string, and then it converts it to lowercase. For faster speed (nothing you would notice), you can just call newStr.toLowerCase() after the loop, so it will do it once instead of every time.
I am trying to sum an array where array length will be provided by user. I have done it but execution time is high then required. What is an efficient way to do it. my code
function summation(){
var p = prompt("Number Only","");
var arr = [] ;
var sum = 0 ;
for (var i = 0; i < p; i++) {
arr.push(parseInt(prompt("Number Only","")));
};
for (var i = 0; i <arr.length; i++) {
sum += arr[i];
};
document.write(sum);
}
(function(){
summation();
})();
Why to use an array when you don't need an array?
function summation(){
var p = prompt("Number Only","");
var sum=0;
for(var i=0;i<p;i++){
sum+=parseInt(prompt("Number Only", ""));
}
document.write(sum);
}
This solution features an infinite loop with break, a prompt with control, a continuing input and a type checking for numbers.
The first imput for the array size is not more necessary, because of the possibillity of immediately ending with cancel or empty input.
function summation() {
var arr = [],
sum = 0,
v;
while (true) {
v = prompt("Number Only (Press [Cancel] for end input)", "");
if (!v) {
break;
}
v = parseInt(v, 10);
if (isFinite(v)) {
arr.push(v);
sum += v;
}
}
document.write('Array: ' + arr + '<br>');
document.write('Sum: ' + sum + '<br>');
}
summation();
With an array, how would I append a character to each element in the array? I want to add the string ":" after each element and then print the result.
var a = [54375, 54376, 54377, 54378, 54379, 54380, 54381, 54382, 54383, 54384, 54385, 54386, 54387, 54388, 54389, 54390, 54391, 54392, 54393, 54394, 54395, 54396, 54397, 54400, 54402, 54403, 54405, 54407, 54408];
For example: 54375:54376:54377
a = a.map(function(el) { return el + ':'; });
Or if you want to join them into a string:
var joined = a.join(':');
If you are looking for a way to concatenate all the elements with :, you can use this
var result = "";
for (var i = 0; i < a.length; i += 1) {
result += a[i] + ":";
}
result = result.substr(0, result.length-1);
Or even simpler, you can do
a = a.join(":");
If you are looking for a way to append : to every element, you can use Array.prototype.map, like this
a = a.map(function (currentItem) {
return currentItem + ":";
});
console.log(a);
If your environment doesn't support map yet, then you can do this
for (var i = 0; i < a.length; i += 1) {
a[i] = a[i] + ":";
}
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)
In Javascript, I have a matrix with a variable number of rows and columns, which I wish to store in a multi-dimensional array.
The problem is that I need extra 3 columns and 3 extra rows with negative indexes in the matrix too. So the result for a 10x10 matrix should be a 13x13 array with indexes from -3 to 9.
I define the array with:
var numberofcolumns = 10;
var numberofrows = 10;
var matrix = [];
for (var x = -3; x < numberofcolumns; x++) {
matrix[x] = [];
}
Is this the right way to do this? Or is there a better way?
While you can create attributes that are negative numbers, you lose some of Javascript's pseudo-array magic. In particular, matrix.length will still be 10 even though it has 13 elements. And the code in general may be surprising to anyone reading it.
You might be better off defining an offset to get the value you need out of the array index and vice-versa:
var offset = 3
for (var x=-3; x<numberofcolumns; x++) {
matrix[x+offset] = []
}
You could define the matrix as an object instead. You would lose some array functionality but you could still access matrix[-3] for example.
var numberofcolumns = 10;
var numberofrows = 10;
var matrix = {};
for (var x = -3; x < numberofcolumns; x++) {
matrix[x] = [];
}
for (x in matrix) {
console.log(matrix[x]);
}
Or you could define your own class starting as an object or array and work from there. Here's something to get you started:
function Matrix() { };
Matrix.prototype.LBound = function()
{
var n;
for (i in this) {
if (!isNaN(i) && (isNaN(n) || n > i))
n = parseInt(i);
}
return n;
};
Matrix.prototype.UBound = function()
{
var n;
for (i in this) {
if (!isNaN(i) && (isNaN(n) || n < i))
n = parseInt(i);
}
return n;
};
Matrix.prototype.length = function()
{
var length = this.UBound() - this.LBound();
return isNaN(length) ? 0 : length+1;
};
Matrix.prototype.forEach = function(callback, indexes)
{
if (!indexes) var indexes = [];
for (var i = this.LBound(); i <= this.UBound() ; i++)
{
indexes[Math.max(indexes.length-1, 0)] = i;
callback(this[i], indexes);
if (this[i] instanceof Matrix)
{
var subIndexes = indexes.slice();
subIndexes.push("");
this[i].forEach(callback, subIndexes);
}
}
};
Matrix.prototype.val = function(newVal)
{
if (newVal)
{
this.value = newVal;
return this;
}
else
{
return this.value;
}
};
Then you'd create your matrix as such
var numberofcolumns = 10;
var numberofrows = 10;
var matrix = new Matrix();
for (var i = -3; i < numberofcolumns; i++) {
matrix[i] = new Matrix();
for (var j = -4; j < numberofrows; j++) {
matrix[i][j] = new Matrix();
matrix[i][j].val("test " + i + " " + j);
}
}
And you can run some cool functions on it
console.log("Upper bound: " + matrix.LBound());
console.log("Lower bound: " + matrix.UBound());
console.log("Length: " + matrix.length());
matrix.forEach(function(item, index)
{
if (item.val())
console.log("Item " + index + " has the value \"" + item.val() + "\"");
else
console.log("Item " + index + " contains " + item.length() + " items");
});
DEMO: http://jsfiddle.net/uTVUP/
I agree with Mark Reed's points about this being a unintuitive use of Array. I think a subclass is in order. You could follow the tutorial here to subclass Array, keep the native bracket notation, and override methods like length() so they give sensible values. Subclassing would have the added advantage of making it clear to those reading your code that something besides your everyday array is going on.