How to .join() arrays nicely - javascript

I find Array.prototype.join() method very useful when constructing strings from arrays, like
"one two three".split(' ').join(', ');
But very often I want to generate a string like this:
"one, two and three"
The method I use is this:
var parts = "one two three".split(' ');
parts.slice(0, parts.length-1).join(', ') + ' and ' + parts.slice(-1)
This generates what I want, however is an ugly solution I should put into a separate function.
I love one liners and believe there should be more elegant one-liner in JS to accomplish this task. Can someone provide me with one ?
EDIT
Please no need to comment that it is a bad practice to write unreadable code. I ask for one! :)
I have learned a lot from one liners about the language constructs and so have a situation where I see a possibility for one. No offense.
FINAL EDIT
I appreciate Pavlo answer as it really shows how easily one liner can become a beautiful readable code. Since I was asking for a one liner so as per my question h2ooooooo gets the highest score.

I'm surprised with the amount of cryptic solutions and the fact that nobody used pop():
function splitJoin(source) {
var array = source.split(' ');
var lastItem = array.pop();
if (array.length === 0) return lastItem;
return array.join(', ') + ' and ' + lastItem;
}
splitJoin('one two three'); // 'one, two and three'
splitJoin('one two'); // 'one and two'
splitJoin('one'); // 'one'
Edit: Modified to properly work for any string.

It's still a function, but why not use a prototype for this?
Array.prototype.joinNice = function() {
return this.slice(0, this.length-1).join(', ') + ' and ' + this.slice(-1);
}
"one two three".split(' ').joinNice();
//one, two and three

I'm surprised no one has pointed out that most of these answers won't work properly with zero or one elements in the array. Here's a simple solution that will work fine for 0+ elements:
function prettyJoin(array) {
return array.length > 1
? array.slice(0, -1).join(", ") + " and " + array.slice(-1)
: array + "";
}
prettyJoin([]); // ""
prettyJoin("one".split(" ")); // "one"
prettyJoin("one two".split(" ")); // "one and two"
prettyJoin("one two three".split(" ")); // "one, two and three"

What about this?
(parts = "one two three".split(" ")).slice(0, parts.length - 1).join(", ") + " and " + parts.slice(-1);

"one two three".split(' ').join(', ').replace(/^(.+),/, "$1, and")
(It even more grammatically correct!)
Though it won't work as expected if last part itself contains a comma.

If you want a one liner
"one, two and three"
A bit more generic..
function splitJoin (str,del,arr) {
for (x=str.split (del),i=x.length;i--;x[i]+=(arr[i]||"")); return x.join("");
}
console.log (
splitJoin ("one two three"," ", [", "," and "])
) //one, two and three

I'm not saying it's pretty though. Or supported in all browsers.
parts.reduce(function(val1, val2, i, arr) {return val1 + (i + 1 < arr.length ? ', ' : ' and ') + val2});

Related

jQuery concatenate variables if both have a value?

I'm really hoping this isn't a duplicate, although certainly possible and I'm just not searching the right terms.
I'm working on my own password strength checker based on flyingcars version.
And I'm trying to work out a way to combine two variables (only if both exist).
Here's what I've got:
var thisVal = $('.password_input').val(),
thisStrength = zxcvbn(thisVal),
thisMeter = $('.password_strength_meter'),
thisLabel = $('.password-text'),
thisSuggestion = $('.password-text-suggest');
thisSuggestion.text(thisStrength.feedback.warning + ". " thisStrength.feedback.suggestions);
If
Would the best way really be to do multiple if statements? Or is there some way of inlining it to the .text() section?
I'm considering extending this further perhaps, by including the time it would take to crack:
thisSuggestion.text(thisStrength.feedback.warning + ". This password could be cracked in: " + thisStrength.crack_times_display['online_no_throttling_10_per_second'] + ". " + thisStrength.feedback.suggestions);
so hopefully multiple if statements can be avoided.
A quick and clean way to do this is to add all of the variables that might contain strings to an array. You can then filter out the blank or falsey values and join the remaining ones with your chosen delimiter.
const a = 'This will be there',
b = '',
c = null,
d = 'So will this';
let result = [a, b, c, d].filter(x => x).join('. ') + '.';
console.log(result);

jquery put comma between every variable except last

I have a script that will insert the checked checboxes and radios in the value() of an input tag.
var burgernavn = meat + " with " + bread + " and " + onion + tomato + cheese + salad;
$('#burger-navn').val(burgernavn);
Onion, tomato, cheese and salad needs to have1 " ," between them, except the last two who need " and " between them.
Thats the first thing.
Second thing is that these variables represent checkboxes, so they can be undefined, in which case they should not be put into $('#burger-navn').val(). They can all be undefined, in which case no commas or "and" should be put in.
I hope this is accomplishable.
Capture all checked values in an array (this makes sure that whatever values in this array, all are defined). Also, it will give you count of values that you need to pass to input box.
var checkedValues = document.getElementsByClassName('checkbox');
Iterate over this array, check for last values. (Check my comments in below code snippet)
var commaValues = "", otherValues= "";
//we are iterating only until (total values -2)
for(var i = 0; i < checkedValues.length - 2 ; i++){
//append comma with each value
commaValues += checkedValues[i].concat(",");
}
//append 'And' for last two values if total valuesa re more than one
if(checkedValues.length > 1){
otherValues = checkedValues[checkedValues.length-1].concat("and", checkedValues[checkedValues.length])
}
else if(checkedValues.length == 1){
otherValues = checkedValues[0];
}
//finally concat both strings and put this concated string in input
$('#burger-navn').val(otherValues.concat(commaValues));
So, I hope you got the idea. This code snippet might need a bit tweak since I didn't had your html code and sample data, but it is easily doable using this snippet as reference. Cheers
You can do this pretty easy with jQuery $.map.
var checkboxes = $('input:checkbox');
var commaString = $.map($('input:checkbox'), function( ele, i ) {
return $(ele).val() + (i + 2 == checkboxes.length ? " and" : (i + 1 != checkboxes.length) ? ",": "");
}).join(" ");

Calculation within Regular Expression

I had a crazy idea.
I want to do a calculation within a regular expression but I'm not sure if it's possible. Basically I have a line that says:
Category:
And every time you click a button it will say:
Category:
Category 1:
Category 2:
etc. I am doing a string of functions on a jQuery selector right now as such:
var newHTML = selector.closest('.row').clone().html().replace(/(Category)(\s)(\d)/g,'$1$2' + (parseInt('$3') + 1)).replace('Category:','Category 2:');
So it does the first replace and if it's the original 'Category' it won't match and will run the second replace. If it does match, I want it to increment the number on the end of the expression by one. I thought maybe I could parseInt() the variable and add one but that doesn't work since parseInt('$3') appears to return NaN and doesn't recognize the variable as an integer.
I know there are plenty of other ways to do this but I just stumbled across it, stumped myself and always like to find any answer to a good question...
Any thoughts? Thanks!
Like in many other languages, JavaScript evaluates the arguments before they are passed to the function. So in your case '$1$2' + (parseInt('$3') + 1)) is evaluated first, which results in the string '$1$2NaN', and that is passed to .replace. parseInt('$3') is NaN because the string '$3' cannot be converted to a number:
> parseInt('$3')
NaN
If you want to perform any computation with the matches, you have to pass a function as second argument:
.replace(/(Category)(\s)(\d)/g, function(match, $1, $2, $3) {
return $1 + $2 + (parseInt($3) + 1));
})
(of course you can name the arguments whatever you want)
You can learn more about passing callbacks to .replace in the MDN documentation.
Further to #FelixKling's answer here is a working demo, just to show what adjustment you might have make.
$('.cat').on('click', function() {
$(this).html(function(i,html) {
return html.replace(/(Category)(\s?)(\d*)/g, function(match, x, y, z) {
y = y || ' ';
z = z || 0;
return x + y + (+z + 1);
});
});
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<div class="cat">Category</div>
<div class="cat">Goint with Category Blah Blah Blah</div>

Making a value plural (Greater than, Less than) in Javascript

I have the following code:
$(function(){
var total_click = 0;
$("#mapKey a.showKey").click(function(){
total_click = total_click + 1;
$("#counter").text("I cheated " + total_click + " whole" + (total_click = 1 ? + ' time' + ((total_click > 1) ? 's ' : ' ') : ''));
return false;
});
});
I'm trying to have it output as such:
Clicked once: "I cheated 1 whole time."
Clicked more than once: "I cheated X whole times."
-- With an 's' at the end of "times".
The counter is working fine, it's just the last part making the "time" or "times" show up appropriately that I am having difficulty with.
Any ideas what I'm doing wrong?
Thanks!
Here is your problem: total_click = 1. Try changing it to total_click == 1. I don't see why you have that conditional in there however, as it won't work as you expect anyway. Try $("#counter").text("I cheated " + total_click + " whole time" + ((total_click == 1) ? ' ' : 's '));
You are not using the ternary operator correctly, and also assigning total_click to 1 instead of checking its value. I would suggest moving this to a function to simplify things.
function pluralize(singular, times) {
if (times == 1) return singular;
else return singular + 's';
}
Then change the string to
var text = "I cheated " + clicks + " whole " + pluralize("time", clicks);
Here's an example.
$(function(){
var total_click = 0;
$("#mapKey a.showKey").click(function(){
total_click = total_click + 1;
$("#counter").text("I cheated " + total_click + " whole " + (total_click == 1 ? "time" : "times");
return false;
});
});
It's okay to use suggested implementations for a trivial cases, however it will not scale for a bigger set of problems and will not work for multiple languages (or it will get ugly very fast).
With this in mind, I’ve created a very simple JavaScript library that can be used to pluralize words in almost any language. It transparently uses CLDR database for multiple locales. It’s API is very minimalistic and integration is extremely simple. It’s called Numerous.
I’ve also written a small introduction article to it: «How to pluralize any word in different languages using JavaScript?».
Feel free to use it in your project. I will also be glad for your feedback on it!

javascript : how can i get array in different ways?

hi i have a little problem with my javascript
can i make the simple way to execute content of array with different character of word?
for example :
var word = new Array();
word [0] = "is";
word [1] = "am";
.
.
.
.
word [100] = "when";
var word should be access with 3 ways,in order to reduce process to execute arrays..
first : " "+ word +" ";
second : " "+ word;
third : word +" ";
-thank you for helping-
I'm not exactly sure what you are chasing (fill me in and I'll update), but I'd like to point out a far better way of filling in that array literal...
var word = [
'is',
'am'
];
You can see the index is calculated automatically, and you are not required to repeat the var name for each member definition.
Update
Maybe you want something you can call and get the next array member each time. This should do it...
function getNextMember(array, startIndex) {
startIndex = startIndex || 0;
return function() {
startIndex++;
return array[startIndex];
};
};
var getNextWord = getNextMember(word);
alert(getNextWord() + ' ' + getNextWord());
See it on jsFiddle.
And of course, if you are feeling naughty, you could add that function to Array's prototype.

Categories

Resources