I have a scenario where given an observable, I would like to know of any elements that never reach any subscribers (ex. filtered out) and take action based on that. What would be the best approach to achieve something like this?
Option # 1
Use a combination of publish and function composition.
var Rx = require('rx')
log = console.log.bind(console),
source = Rx.Observable.interval(100).take(100);
published = source.publish(),
accepted = published.where(condition),
rejected = published.where(not(condition));
accepted.subscribe(log.bind(undefined, 'accepted: '));
rejected.subscribe(log.bind(undefined, 'rejected: '));
published.connect();
function condition (x) {
return x % 4 === 0;
}
function not (func) {
return function () {
return !func.apply(this, arguments);
}
}
Option # 2
Tag (mutate) the events and filter at the last second.
var Rx = require('rx')
log = console.log.bind(console),
source = Rx.Observable.interval(100).take(100);
source
.map(toAcceptable)
.doAction(function (x) {
x.acceptable = x.acceptable && condition1(x.value);
})
.doAction(function (x) {
x.acceptable = x.acceptable && condition2(x.value);
})
.doAction(function (x) {
log(x.acceptable ? 'accepted:' : 'rejected:', x);
})
.subscribe();
function condition1 (x) {
return x % 4 === 0;
}
function condition2 (x) {
return x % 3 === 0;
}
function toAcceptable (x) {
return {
acceptable: true,
value: x
};
}
Related
Let's consider I have the following function call,
function add(){
x = 0 ;
for(i = 0 i < ##; i++){ // need to run a loop four times
x+=1
}
}
Let's consider I am trying to Implement the function that will add one on each subsequent call, like below
console.log(add()()().getValue()); // 3
console.log(add().getValue()); // 1
console.log(add()().getValue()); // 2
A call to add must return a function which also has a getValue method, and each call to that function must return the same thing. So:
function add() {
var x = 1;
function inner() {
x += 1;
return inner;
}
inner.getValue = function () {
return x;
}
return inner;
}
console.log(add()()().getValue()); // 3
console.log(add().getValue()); // 1
console.log(add()().getValue()); // 2
My guess is they were expecting you to use toString() which is not the greatest way of doing this.
function add(x = 0) {
function next() {
return add(x+1);
}
next.toString = function () {
return x;
};
return next;
}
console.log("example 1", add()()()());
console.log("example 2", add()()()()()()()()());
I think you are trying to emulate the behavior of generator functions. Here is a snippet that illustrates one way you could do it with a generator.
function* adder() {
let x = 0;
while (true) {
yield x + 1;
x++;
}
}
const add = adder();
const firstValue = add.next();
const secondValue = add.next();
const thirdValue = add.next().value;
This is the test code that it's supposed to pass
function makeArray() {
const array = [];
const t = 10;
for (let i = 0; i < t; i++) {
array.push("I am a strange loop.");
}
return [array, t];
}
describe('loops', () => {
jsdom({
src: fs.readFileSync(path.resolve(__dirname, '..', 'loops.js'), 'utf-8'),
});
describe('forLoop(array)', () => {
it('adds `"I am ${i} strange loop${i === 0 ? \'\' : \'s\'}."` to an array 25 times', () => {
const [array, t] = makeArray();
const strangeArray = forLoop(array);
const testArray = strangeArray.slice(array.length);
const first = "I am 1 strange loop.";
const rest = "I am 24 strange loops.";
expect(strangeArray[11]).to.equal(first);
expect(strangeArray[34]).to.equal(rest);
expect(strangeArray.length).to.equal(t + 25);
});
});
});
this is my code to return the function to strangeArray what I am thinking is that 35 is the total number of members in the array and as the test pass requires me to have 'expect(strangeArray[11]).to.equal(first)' 11th value to be equal to my function return as
"I am 1 strange loop."
function forLoop(array) {
for (let i = 0; i < 35; i++) {
if (array[i] === "I am a strange loop.") {
return;
}
else {
array.push("I am ${i} strange loops.");
}
}
return [array,i];
}
Not sure what you mean exactly but I guess you just want the test to pass? The problem is that the first loop has 'loop' as singular and your indexes don't work either since they would start at 11. That's why your code doesn't work. You can just push to the original array.
function forLoop(array){
for(let i = 0; i < 25; i++){
array.push(`I am ${i} strange loop${i > 1 ? '' : 's'}.`)
}
return array
}
I am trying to learn Typescript in combination with some exercises. I can't figure out why I am getting this error of too much recursion. I made some wrapper-functions.
Wrapper-functions
type Fun<a,b> = {
f: (i:a) => b
then: <c>(g:Fun<b,c>) => Fun<a,c>
}
let myFunction = function<a,b>(f:(_:a) => b) : Fun<a,b> {
return {
f:f,
then: function<c>(this:Fun<a,b>, g:Fun<b,c>) : Fun<a,c> {
return then(this,g);
}
}
};
let then = function<a,b,c>(f: Fun<a,b>, g:Fun<b,c>) : Fun<a,c> {
return myFunction(a => g.f(f.f(a)))
};
I'd like to create my own RepeatFunction so to say, whereas I can pass a function and an amount of executes as parameters.
My code
let increase = myFunction<number,number>(x => x + 1);
let RepeatFunction = function<a>(f: Fun<a,a>, n: number) : Fun<a,a> {
if (n < 0)
{
return myFunction(x => f.f(x));
}
else
{
for (let i = 0; i < n; i++)
{
RepeatFunction(myFunction<a,a>(x => this.f(x)), n); //error in console
}
}
};
console.log(RepeatFunction(increase, 2).f(10));
I'd like to call RepeatFunction, pass in my increase-function with to execute 2 times on number 10.
I am getting the error: 'Too much recursion'. Could anyone tell me what I am missing here? There are no syntax errors.
edit 2
let RepeatFunction = function<a>(f: Fun<a,a>, n: number) : Fun<a,a> {
if (n < 0)
{
return myFunction(x => f.f(x));
}
else
{
return RepeatFunction(myFunction<a,a>(x => f.f(x)), n - 1);
}
};
console.log(RepeatFunction(incr, 1).f(10)); // answer is: 11
console.log(RepeatFunction(incr, 5).f(10)); // answer is: 11
console.log(RepeatFunction(incr, 50).f(10)); // answer is: 11
The problem is that this is infinitely recursive because n never changes in value, you always call RepeatFunction with the same n. My guess is you want to call it n times, so you should decrease n next time you call it, or you can use an iterative version :
let RepeatFunction = function<a>(f: Fun<a,a>, n: number) : Fun<a,a> {
if (n < 1)
{
return myFunction(x => f.f(x));
}
else
{
var fn = myFunction<a,a>((x) => f.f(x));
for (var i = 0; i < n; i++) {
fn = fn.then(f);
}
return fn;
}
};
Let me propose an example that works, then follow up with what fails, highlighting the point to my question.
Here, we have 3 functions being called (1 named, 2 anonymous):
var add = function(a, b) {return a+b};
var multiply = function(a, b) {return a*b};
function myFunction(fxn) {
return function(x) {
return function(y) {
return fxn(x,y);
}
}
}
myFunction(add)(2)(3)
Understandably, this call fails:
myFunction(add)(2)(3)(4)
How would I detect how many functions are being called? In the 2nd call, I'm calling 4 functions (1 named, 3 anonymous).
How would I rewrite the myFunction function in a way that compensated for any given amount of calls? I know we can detect how many arguments a function was given, but is there a way to detect how many functions are being called? I hope I worded this correctly. Thanks.
To find out if a variable contains a reference to a function you can use below code:
if (typeof(v) === "function") alert("This is a function")
Based on above you can find out on how many nested functions there are
function myFunction() {
return function() {
return function() {
return 1 + 2;
}
}
}
var count = 0;
var v = myFunction();
while (typeof(v) === "function") {
count++;
v = v();
}
alert("Nr of nested functions: " + count)
Even if this has no practical use case I can think of, this is a possible solution:
var add = function(a, b) {
return a + b
};
var multiply = function(a, b) {
return a * b
};
var counter = 0;
var result = 0;
function myFunction(fxn) {
counter = 1;
result = 0;
return function first(x) {
++counter;
return function second(y) {
++counter;
x = result ? result : x;
result = fxn(x, y);
return second;
}
}
}
myFunction(add)(1)(2)(3)(4);
alert('Result is: ' + result + '; Parentheses count: ' + counter);
I am new to json. My json array
[{"seat_number":"834"},{"seat_number":"8F3"},{"seat_number":"891"},
{"seat_number":"814"},{"seat_number":"4081"},{"seat_number":"8F1"},
{"seat_number":"8F9"},{"seat_number":"4039"},{"seat_number":"0"},
{"seat_number":"509"},{"seat_number":"662"},{"seat_number":"561"},
{"seat_number":"791"},{"seat_number":"849"}]
I want to find seat number already exist in array.
if(($scope.employeeSeat.seat_array.indexOf($scope.employeeData.new_seat_number))>-1)
{
alert('Seat number is already assigned.Please Check');
}
What is wrong?
You can do it the hard way if you want
var data = [
{"seat_number":"834"},{"seat_number":"8F3"},
{"seat_number":"891"},{"seat_number":"814"},
{"seat_number":"4081"},{"seat_number":"8F1"},
{"seat_number":"8F9"},{"seat_number":"4039"},
{"seat_number":"0"},{"seat_number":"509"},
{"seat_number":"662"},{"seat_number":"561"},
{"seat_number":"791"},{"seat_number":"849"}
];
function matchingSeat(x) {
return data.some(function(elem) {
return elem.seat_number === x;
});
}
console.log("831", matchingSeat("834")); // 834 true
console.log("8F3", matchingSeat("8F3")); // 8F3 true
console.log("999", matchingSeat("999")); // 999 false
I think that's a total pain tho. Once you have some reusable utility functions at your disposal, this problem becomes a lot easier to solve.
Don't freak out: the ES5 solution is below
// ES6
// reusable lib
let prop = y => x => x[y];
let comp = f => g => x => f(g(x));
let eq = y => x => x === y;
let some = f => xs => xs.some(f);
Now write some helpers to solve your task
let eqSeat = x => comp(eq(x))(prop("seat_number"));
let hasSeat = comp(some)(eqSeat);
Check it out
console.log("831", hasSeat("834")(data)); // 831 true
console.log("8F3", hasSeat("8F3")(data)); // 8F3 true
console.log("999", hasSeat("999")(data)); // 999 false
Here's the same code in ES5
// ES5
// reusable lib
var prop = function prop(y) {
return function (x) {
return x[y];
};
};
var comp = function comp(f) {
return function (g) {
return function (x) {
return f(g(x));
};
};
};
var eq = function eq(y) {
return function (x) {
return x === y;
};
};
var some = function some(f) {
return function (xs) {
return xs.some(f);
};
};
Your helpers
var eqSeat = function eqSeat(x) {
return comp(eq(x))(prop("seat_number"));
};
var hasSeat = comp(some)(eqSeat);
Try it out
console.log("831", hasSeat("834")(data)); // 831 true
console.log("8F3", hasSeat("8F3")(data)); // 8F3 true
console.log("999", hasSeat("999")(data)); // 999 false
Note that ({a:10}) !== ({a:10}), therefore your indexOf won't work. See this related question.
Knowing that, there are several ways to do this (assuming typeof $scope.employeeData.new_seat_number === 'string'):
1) Use a for-loop:
for (var i = 0; i < $scope.employeeSeat.seat_array.length; i++) {
if ($scope.employeeSeat.seat_array[i].seat_number === $scope.employeeData.new_seat_number) {
alert('Seat number is already assigned.Please Check');
}
}
2) Use .some:
if ($scope.employeeSeat.seat_array.some(function(seat) { return seat.seat_number === $scope.employeeData.new_seat_number; })) {
alert('Seat number is already assigned.Please Check');
}
Note: .some is the best answer other than the good old for-loop in my opinion. The rest are explorations of the Array API.
3) Use .findIndex:
if ($scope.employeeSeat.seat_array.findIndex(function(seat) { return seat.seat_number === $scope.employeeData.new_seat_number; }) !== -1) {
alert('Seat number is already assigned.Please Check');
}
4) Use .find:
if ($scope.employeeSeat.seat_array.find(function(seat) { return seat.seat_number === $scope.employeeData.new_seat_number; })) {
alert('Seat number is already assigned.Please Check');
}
Note: .find and .findIndex are experimental technologies. Check their compatibility tables to see if .find is available for your browser. If not, use their poly fills.
5) Use .map:
if ($scope.employeeSeat.seat_array.map(function(seat) { return seat.seat_number; }).indexOf($scope.employeeData.new_seat_number)) !== -1) {
alert('Seat number is already assigned.Please Check');
}
Note: Using .map will be much slower as .map iterates through the array running a function that will be used to create a brand new array.
for(var i = 0; i < myjson.length; i++)
{
if(myjson[i].seat_number == expectednumber)
{
alert('Seat number is already assigned.Please Check')
}
}
the item in your array is a object, so you can not use indexOf to find the seat_number.
you can try:
for(var i=0; i<$scope.employeeSeat.seat_array.length; ++i){
if($scope.employeeData.new_seat_number == $scope.employeeSeat.seat_array[i].seat_number){
alert('Seat number is already assigned.Please Check');
}
}
You can use array find prototype. You may find detail on this method here.
Example:
var items = [{"seat_number":"834"},{"seat_number":"8F3"},{"seat_number":"891"},{"seat_number":"814"},{"seat_number":"4081"},{"seat_number":"8F1"},{"seat_number":"8F9"},{"seat_number":"4039"},{"seat_number":"0"},{"seat_number":"509"},{"seat_number":"662"},{"seat_number":"561"},{"seat_number":"791"},{"seat_number":"849"}];
var newSeatNumber = $scope.employeeData.new_seat_number;
var result = items.find(function(item) {return item.seat_number == newSeatNumber ;})
console.log(result); // Object { seat_number="791"} if found, else undefined
if(result)
{
//Do your stuff. Item exits in array
}
Try this. Make use of filter(). If arr is empty, then it should show the alert.
var arr=$scope.employeeSeat.seat_array.filter(function(item){
return $scope.employeeData.new_seat_number == item.seat_number;
})
if(!arr.length){
alert('Seat number is already assigned.Please Check');
}
You can also make use of some().
var bool=$scope.employeeSeat.seat_array.some(function(item){
return $scope.employeeData.new_seat_number == item.seat_number;
})
if(bool){
alert('Seat number is already assigned.Please Check');
}
Why do you need such a JSON Structure ?
I've changed the structure a little.
{
"seat_numbers" :["894", "900", "814", "591", "789", ..]
}
Load your JSON using javascript/jquery
var yourSearchingSeat = "900";
$.getJSON( "ajax/test.json", function( data ) {
var seat_numbers = data.seat_numbers
for (i=0; i<seat_numbers.length;i++) {
if (seat_numbers[i] == yourSearchingSeat) {
console.log("Seat number"+yourSearchingSeat+" already exists");
}
}
});