I've written the following function in Typescript:
public searchPosts(keyword ? : string): Post[] {
return this._posts.filter(function(post) {
if (post.title.search(new RegExp('money', 'gi')) >= 0) {
return post;
}
});
}
It's working just fine but, I need to make it a little dynamic so that instead of hardcoded value i.e. money, I can put my keyword variable in RegExp (new RegExp(keyword, 'gi')). But doing so does not return anything even for 'money' as a keyword.
Any ideas on what I'm doing wrong here?
This is how it should work
var keyword = '345';
var f = ['1234', '3456'].filter(function(post) {
return (post.search(new RegExp(keyword, 'gi')) >= 0);
});
console.log(f);
This is your function in pure JS
var posts = [{title: '1234'}, {title: '3456'}];
function searchPosts (keyword) {
return posts.filter(function(post) {
return (post.title.search(new RegExp(keyword, 'gi')) >= 0);
});
}
console.log(searchPosts('345'));
If this doesnt work, the problem is somewhere else ;].
Related
I got asked this in an Interview and I couldn't solve it. Was wondering if any of you guys can help me.
fn("hello").fn("world").fn("!!!").fn();
function fn (str){
// Enter Solution Here
}
The solution should return 'hello world !!!'.
I tried method chaining and was able to get a partially right answer which is as follows:
function fn(str) {
var string = str;
this.fn1 = function(str1) {
string += " "+str1;
return this;
}
this.fn = function() {
console.log(string)
}
}
new fn("hello").fn1("world").fn1("!!!").fn();
but as you can see I cant get it to work unless I use fn1 as the function to concat the string. Any help will be appreciated, thanks.
Have the function return an object with one fn method. If, when you call it, it has an argument, update the string, otherwise return the string so you can log it.
function fn(str = '') {
return {
fn: function (s) {
if (s) {
str += ` ${s}`;
return this;
}
return str;
}
};
}
const output = fn('hello').fn('world').fn('!!!').fn();
console.log(output);
Additional documentation
Template/string literals
You could return an object with two properties, one for returning the complete string and another for collecting parts and retuning the object.
function fn(str) {
const
fns = {
fn: function () {
return str;
},
fn1: function (s) {
str += ' ' + s;
return fns;
}
};
return fns;
}
console.log(fn("hello").fn1("world").fn1("!!!").fn());
I think this should do the trick:
function fn(s){
return new function(){
this.str = s;
this.fn = (ns) => {if(ns){this.str += " "+ns; return this;} else return this.str;};
}
}
let a = fn("hello").fn("world").fn("!!!").fn();
console.log(a);
Seems like you need to use objects
const generic = {
"fn1":null,
"current":"",
"fn": () => {
//what do you want to do with "this.current"?
}
}
function fn(str) {
var ret = generic;
ret.fn1 = (wa) =>{
var again = generic;
again.current +=wa;
return again;
}
ret.current += str;
return ret;
}
You can return an object with a .fn() method which will
check if an argument is passed in or not to determine when to terminate the chain or continue chaining.
When no argument is sent, then it simply returns the accumulated string.
Otherwise, it calls fn() function again to accumulate to the string and get the next copy of the same structure as before:
const result = fn("hello").fn("world").fn("!!!").fn();
console.log(result);
function fn (str){
return {
fn(nextString) {
if (nextString === undefined)
return str;
return fn(`${str} ${nextString}`);
}
};
}
Since this operation is immutable, it means each link in the chain is independent, therefore it is no problem with assigning to variables to continue with different chains:
const helloWorld = fn("hello").fn("world");
const one = helloWorld.fn("one").fn();
const two = helloWorld.fn("two").fn();
const three = helloWorld.fn("three").fn();
console.log(one);
console.log(two);
console.log(three);
function fn (str){
return {
fn(nextString) {
if (nextString === undefined)
return str;
return fn(`${str} ${nextString}`);
}
};
}
I'm defining a processor method that returns the lower-case version of the content to achieve this behaviour:
> phrase = new TranslatedPhrase("recognize", "reconocer");
> phrase.palindrome();
true
function reverse(string) {
return Array.from(string).reverse().join("");
}
function Phrase(content) {
this.content = content;
this.processor = function(string) {
return string.toLowerCase();
}
this.processedContent = function processedContent() {
return this.processor(this.content);
}
// Returns true if the phrase is a palindrome, false otherwise.
this.palindrome = function palindrome() {
return this.processedContent() === reverse(this.processedContent());
}
}
function TranslatedPhrase(content, translation) {
this.content = content;
this.translation = translation;
// Returns translation processed for palindrome testing.
this.processedContent = function processedContent() {
return this.processor(this.translation);
}
}
I also tried return this.string.toLowerCase(); but this also doesn't work.
The error I'm currently getting is this:
> let phrase = new TranslatedPhrase("recognize", "reconocer");
undefined
> phrase.palindrome();
Thrown:
TypeError: phrase.palindrome is not a function
Any suggestions as to what I'm missing are greatly appreciated, thx!
I need your help communty, i have written a code to reverse a function but the problem is that am not able to check for palindrome, any help will be appreciated.
here is the code to reverse a string
function reverseString(str) {
return str.split("").reverse().join("");
};
the problem is how to check for palindrome am totally confused. Sorry community i am suppose to run it against a test and it is not passing properly, that's the problem.
Here is the Test spec wriiten in jasmine.
describe("Produce the reverse order of a word: ", function () {
describe("Case for en empty string", function() {
it("should return null for empty string", function() {
expect(reverseString('')).toEqual(null);
});
});
describe("Case for palindromes", function() {
it("should return true for `anna`", function() {
expect(reverseString('anna')).toEqual(true);
});
it("should return true for `NaN`", function() {
expect(reverseString('NaN')).toEqual(true);
});
it("should return true for `civic`", function() {
expect(reverseString('civic')).toEqual(true);
});
});
describe("Case for normal words", function() {
it("should return `skoob` for `books`", function() {
expect(reverseString('books')).toEqual('skoob');
});
it("should return `nomolos` for `solomon`", function() {
expect(reverseString('solomon')).toEqual('nomolos');
});
it("should return `csim` for `misc`", function() {
expect(reverseString('misc')).toEqual('csim');
});
});
});
Here is a code written by a friend in ECMA6 and it works by using a single function block. i don't want to use his code so i don't look like copy cat and is against the rule anyway just want to write my own code. Though we are still allowed to write it in ECMA 5
here is his code
const reverseString = (stringToReverse) => {
reversedString = "";
if (stringToReverse) {
for (i = String(stringToReverse).length; i >= 0; i--) {
reversedString += stringToReverse[i];
}
} else {
return null;
}
if (reversedString.substring(9) === stringToReverse) {
console.log(true);
return true;
}
return `${reversedString.substring(9)}`;
};
module.exports = reverseString;
To be able to catch palindromes such that one, you have to also remove characters like comma and dot. A simple way to do this is removing non-alphanumeric characters:
function palindrome(str) {
var re = /[^0-9a-z]/gi;
var lowRegStr = str.toLowerCase().replace(re, '');
var reverseStr = lowRegStr.split('').reverse().join('');
return reverseStr === lowRegStr;
}
palindrome("A man, a plan, a canal. Panama");
EDIT: the regex used by OP was already fine. So the question is not really necessary. Nothing to be done.
I wrote this fast-templating function:
var templatize = function(string) {
return function (string) {
return string.replace(/{{(.*?)}}/g, function(pattern, match) {
value = this[match];
if (value) {
return value;
} else {
return pattern;
}
});
}.call(this, string);
}
Which does this:
var foo = "bar", bar = "foo";
templatize("We are {{foo}} and {{bar}}, but not {{crazy}}"); // "We are bar and foo but not {{crazy}}"
I'm quite happy with this except that I have scoping problem. For sure, the templatize method will be accessible through namedscope, but then, the current context of execution of templatize is not accessible in my function automatically.
Something like calling $.proxy(templatize, this)("We are {{foo}} and {{bar}}, but not {{crazy}}") should work, right?
But I'd like to achieve this without needing to call $.proxy() (and without any jQuery preferably) so that context is automatically transfered to the execution one.
I'm struggling with .call(), .apply(), and other closures, but I think I read somewhere over the internet that it was possible. Thanks
You can avoid using jQuery doing this :
var templatize = function(string) {
var me = this; // the data source
return string.replace(/{{(.*?)}}/g, function (full, key) {
// "this" refers to the string itself
return me[key] || full;
});
}
In case you want to use jQuery.proxy(), wrap the replacement function :
var templatize = function(string) {
return string.replace(/{{(.*?)}}/g, jQuery.proxy(function (full, key) {
// "this" now refers permanently to the data source
return this[key] || full;
}, this));
}
In both cases you can bind the data source to this using call :
templatize.call({ hello: 'Hi!' }, '{{hello}}');
Going further
You could optimize by compiling the template for reuse :
function compile(tpl) {
var i = -1, tmp = [];
tpl = tpl.split(/{{([^{}]+)}}/);
while (++i < tpl.length) {
if (i % 2) tmp.push('this["' + tpl[i] + '"]');
else if (tpl[i]) tmp.push('"' + tpl[i].replace(/"/g, '\\"') + '"');
}
return new Function(
'return [' + tmp.join() + '].join("");'
);
}
Usage example :
var tpl = compile('{{hello}} {{hello}}');
tpl.call({ hello: 'Hi!' }); // "Hi! Hi!"
tpl.call({ hello: 'Yo!' }); // "Yo! Yo!"
Regarding the example above, here is the function returned by compile :
function () {
return [this["hello"]," ",this["hello"]].join("");
}
Note that you can use an array as well :
var tpl = compile('{{1}} {{0}}');
tpl.call(['a', 'b']); // "b a"
Performance test : http://jsperf.com/template-compiling.
why don't you pass an object containing the view variables? would be cleaner then potentially displaying any existing variable in your view.
var templatize = function(string, variables) {
return function (string) {
return string.replace(/{{(.*?)}}/g, function(pattern, match) {
value = variables[match];
if (value) {
return value;
} else {
return pattern;
}
});
}.call(this, string);
}
I was reading through fluent api I got a doubt.
I want to take in a string upon which a jQuery function or example is called upon
Function
function compareThis(newString) {
function compare(newString) {
if (this == newString) {
alert("same string");
} else {
alert("differnt string");
}
}
}
Where it is called as
("alerting").compareThis("alerted").compare(); //alert 'different string'
I want to pass the data/string not as parameter but as called upon.
JSFiddle
Note: I would like to call the function in similar cases like finding date interval etc
You can use prototype to add function to String class:
String.prototype.compare = function(newString){
if (this == newString) {
alert("same string");
} else {
alert("differnt string");
}
};
I think you should adapt the code for your function, but it's the idea.
Maybe I missed interpreted however, it looks as it you required a form of method chaining to compare string. To do this you can create a variable and create functions inside it.
var compare = (function(){
var thisString;
var stringToCompare;
var create = function(sVal) {
thisString = sVal;
return this;
};
// Public
var compareThis = function(sVal) {
stringToCompare = sVal;
return this;
};
var compare = function(anotherString) {
return thisString == stringToCompare;
};
return {
create: create,
compareThis: compareThis,
compare: compare
};
}());
var b = compare.create('test').compareThis('test').compare();
alert(b);
Example fiddle