Array Reduce functionality that is happening in the following code - angularjs

Hi I am looking into Angular 2.0 source code examples in https://angular.io/
I came across this following code. The function "remaining" essentially gets the number of elements in todos array where done is false. It is working fine, I just want to understand what's happening in reduce function. I have basic idea of how reduce function works, but could not understand the syntax here, particularly count+ +!todo.done . I am new to typescript.
export class TodoApp{
todos: Todo[] =[
{text:"learn angular",done:true},
{text:"build angular app",done:false}
];
get remaining(){
return this.todos.reduce((count:number,todo:Todo) => count+ +!todo.done, 0);
}}

If you understand how reduce method works, then you know that the part in callback is supposed to return sum of two values, namely, increment - if task is undone (add 1) or add nothing (zero) if task is done, done equal to true.
This is exactly what this line does
count + +!todo.done
The part +!todo.done is just a confusing type casting and could be rewritten as
count + Number(!Boolean(task.done))
And now it should be clear because toNumber conversion of boolean values follows simple rule (ECMAScript spec): 1 for true, 0 for false.

Related

Why was I able to get away with not using a splat operator sometimes

I have some ruby code from my Ruby on Rails project.
I am formatting some data so I am calling attributes.extract! to get the fields I need from my model.
I noticed recently that every now and then the data wouldn't get extracted as expected. I realized that I needed a splat operator. But it is strange because I do notice that sometimes when the method is called in my Rails project it will sometimes extract the data without the use of the splat operator. But when I run the code from my Rails console it never extracts the data unless I add the splat operator.
Here is the code in question
# in a service file, let's call it service.rb
def self.format_user_home_address_data(user)
# This doesn't work in the console but sometimes works when run in my Rails project
home_address_data = user.attributes.extract!(User::HOME_ADDRESS_FIELDS)
home_address_data[:address_type] = "home"
home_address_data
end
# at the end this method will sometimes return { address_type: "home" } or
# sometimes it'll actually return the extracted attributes as expected
HOME_ADDRESS_FIELDS is just an array with the values ["address_line_1", "city", "state", "zip"]
Anyway I know that to get it to run correctly I need to do this
home_address_data = user.attributes.extract!(*User::HOME_ADDRESS_FIELDS)
But does anyone know why I was able to get away without adding the splat operator for so long? Is there some Ruby on Rails magic that is only sometimes happening? What's the deal?
Well, let's check it out. There is no any magic behind attributes.extract! in the end. Here is an actual implementation of this method from Rails source code:
def extract!(*keys)
keys.each_with_object(self.class.new) { |key, result|
result[key] = delete(key) if has_key?(key)
}
end
Link: click. As you can see, it creates new hash, goes over the keys one by one and moves value from self to this new array. So, if you give an Array argument to this method then key in the block will be an Array as well. So, it won't be found. So, no way it may work for array argument. The only one possibility is that something else is passed instead of User::HOME_ADDRESS_FIELDS.

How do deal with nested Arrays/objects in BehaviorSubjects, Observables?

I generally have problems using rxjs with nested Objects or Arrays.
My current use-case is this:
{a: [
{b: 0, c:[{d:1}]},
{b: 1, e:[{f: 'someString'}]}
]
Task: Get and set the Observable or value of a,b,c,d,e,f. I also want to be able to subscribe to each property.
I had this Problem in a similar use-case with an Array of BehaviorSubjects:
Efficiently get Observable of an array BehaviorSubjects
I generally have problems to use the basic functionality of nested arrays/objects in rxjs.
The basic functionality I mean includes:
Array:
getting Element by Index
using for of/in on Arrays
setting an Element by Index
push, pop, shift, slice, splice, ...
Object:
getting Value by Property name
going into the nested tree: object.key1.key2.key3[3].key4 ...
setting Value by Property name
assign
for of/in loops
Generally:
Destructuring: e.g.: let [variable1, variable2] = someObject;
Maybe other stuff I forgot.
I dont know if and which functions are possible for which rxjs Objects and which make sense (for example you should be able to set values in an Observable directly). But coming from a background without rxjs, I have trouble to manage my rxjs Objects properly.
I think reason for this besides my lack of knowledge and understanding is, that
a. The rxjs Objects don't provide the functionality as I'm used to from normal arrays and objects. e.g.:
let variable1 = array[1].property;
//becomes this (see related stack-Question I mentioned earlier)
let variable2 = array.pipe(mergeMap(d=> d[index].pipe(map(d1 => d1[property]));
// -> what happens here? You first need to know what mergeMap,
// map is doing and you have 5 levels of nested inline functions.
b. To implement the those mentioned functionalities I need to go over the .pipe() function and use some function like mergeMap, map, pluck, ... Functions that aren't directly indicating that you can get the Observable of let's say 'e' in my example. Making something like object.a[1].e wierd to implement (at least I don't know how to do that yet)
EDIT:
I also want to note, that I still love the idea of rxjs which works well in angular. I just have problems using it to it's full extend, as I'm a bit new to angular and consequently rxjs.
I thin RX is mainly focus on dealing with async operations. Mutation of array and object we can perfectly use the methods comes natively with javascript if theres no existing operators. or you can create your own operator for mutation/iteration etc.
Will try to answer some of your question on array/objects mutation, they are actually very straight forward.
Array:
getting Element by Index
map(arr=>arr[index])
using for of/in on Arrays
map(arr=>arry.map(item=>....))
setting an Element by Index
tap(arr=>arr[index]=somevalue)
Object:
getting Value by Property name
pluck('name')
going into the nested tree: object.key1.key2.key3[3].key4 ...
pluck('key1','key2')
setting Value by Property name
map(obj=>({a:value,obj...}))
assign
lets say your really want some pick array index method as rxjs operator you can create something like, same as for..in operations.
const pluckIndex=(index)=>source=>source.pipe(map(arr=>arr[index]))
const source = of([2,3])
source.pipe(pluckIndex(1)).subscribe(x => console.log(x));

Test action outputs length

In my Logic App workflow, I'm trying to evaluate a condition for the previous action outputs array.
My condition expression
#less(action('Get_items').outputs.length, 1)
results in error
action 'Item_found' completed with status 'Failed' and code 'BadRequest'.
The same happens for
#greater(action('Get_items').outputs.length, 1)
as well as
#empty(action('Get_items').outputs)
What am I doing wrong here?
Background: The action('Get_items') is query retrieving items from a SPO site list using a Filter Query.
The action succeeds but the App Run Trace doesn't show any details on the outputs, in this case the expected empty array.
I managed to achieve the desired condition evaluation by correctly accessing the array the same way a for-each action does:
#empty(body('Get_items')['value'])
The documentation doesn't give a hint on this.
Accepted solution was not working for me for CDS entities, so I have solved it by using such condition:
#length(body('Get_items')['value'])
If I understand correctly it is converting array to string and empty array is converted to [], so you just have to check if the output of query is more than 2, then it means Get_Items is not empty.

Programmatically composing a chain

I would like to be able to programmatically compose a chain, for later inclusion in another chain. I know it can't be that hard, but I seem to be missing something.
In theory, I should be able to do something like this:
var c = ??? // the part I can't figure out
List( 1, 2, 3 ).foreach {
c.exec( http("Fetch something").get("..." + _ ) )
}
That is, I expect to be able to create a chain, then populate that chain in a loop, rather than hard-coding the chain in the source code.
My biggest struggle, I think, is knowing what to assign to c. I had assumed that it should be
var c = new ChainBuilder()
but according to the documentation I have to pass it a list of actionBuilders and the next action, implying that it is not possible to build an empty chain and then build on it in a separate statement.
Is there any way to make my .foreach loop work the way I intend it to work?
The answer is
import bootstrap._
and then
var c = bootstrap
But then the loop must be modified, like so:
List( 1, 2, 3 ).foreach( x => {
c = c.exec( ... )
})
The reason has to do with the fact that you have to do what chaining does. When you have
foo()
.bar()
.blip()
The result of the whole expression is the return value from blip and not foo - which is obvious when you think about it - so the variable that we are attaching to has to move as nodes are attached.
I hope someone, somewhere, besides me, finds value in seeing this example.

Angularjs e2e testing past/future comparisons

I'm currently trying to figure out if there is a way to do a simple future/past comparison ex.
1) Check state of list by getting list length
2) Perform action which if success increments the list
3) Compare the current list length to the past.
But the concepts of Futures seems to get in my way. One would think this is a pretty normal use case.
Q: How would you go about handling past/future comparisons in Angularjs Scenario?
It's kind of longwinded, but you can define custom matchers which understand futures. For example:
angular.scenario.matcher('toBeGreaterThanFuture', function(future) {
return +this.actual > +future.value;
});
Use like:
listLengthBefore = repeater('.td').count();
// Do some stuff.
listLengthAfter = repeater('.td').count();
expect(listLengthAfter).toBeGreaterThanFuture(listLengthBefore);

Resources