Is Javascript's Array.sort an example of Inversion of Control? - inversion-of-control

In Javascript's sort method of an Array, I can pass a customized sorting function. Example:
const data = [ { name: "Tom", age: 10 },
{ name: "Dick", age: 9 },
{ name: "Harry", age: 12 }
];
function mySort(A, B) {
return A.age - B.age;
}
data.sort(mySort);
console.log(data);
Is such a paradigm considered inversion of control?

Related

MongoDB : projection matches all element corresponding to query

Supposing the following data format
{
_id: "1234",
tag: "MyTag",
members: [{
name: "James", age: 54
}, {
name: "John", age: 22
}, {
name: "Eric", age: 36
}],
},
{
_id: "7896",
tag: "MyTag2",
members: [{
name: "Philip", age: 6
}, {
name: "Mark", age: 14
}, {
name: "Maya", age: 64
}],
}
How can I request all the person over 30 to get that result
{
_id: "1234",
tag: "MyTag",
members: [{
name: "James", age: 54
}, {
name: "Eric", age: 36
}],
},
{
_id: "7896",
tag: "MyTag2",
members: [{
name: "Maya", age: 64
}],
}
Basically this request
db.MyDB.find({'members':{'$elemMatch':{'age':{'$gt':30}}}}, {'tag:1', 'members.$':1})
but where the .$ operator does not return only the first or each list
(I'm using python api but I think the question applies more generally)
Thanks a lot!
The positional operator $ and the $elemMatch projection operator both only match the first element that matches the query.
If you want to get all elements that match, use aggregation and $filter the array.

Cosmos DB query without knowing the key for object

Single document example:
{
"id" : "xxxxxx",
"properties": {
"a_prop": {
type: "names",
value: "John",
},
"b_prop": {
type: "score",
value: 5.5,
},
"c_prop": {
type: "names",
value: "Steve",
}
}
}
Question - how can I get documents that has at least one property with type "names" ?
Struggle is that I cannot know before that property "a_prop" is a type of "names".
It's no fun to query when your model has collections of objects with unknown, arbitrary keys. Consider changing model to have known keys and store the unknowns as property values. For example, changing properties to an array of items:
{
id: "xxxxxx",
properties: [
{
name: "a_prop",
type: "names",
value: "John",
},
{
name: "b_prop",
type: "score",
value: 5.5,
},
{
name: "c_prop",
type: "names",
value: "Steve",
}
]
}
Now the array-based query for items with a property of type "names":
SELECT * FROM c
WHERE ARRAY_CONTAINS(c.properties, {"type": "names"}, true)
See also discussion for this question.

How to iterate over multiple arrays without nested observables

I must iterate over array, find correspondent objects in other array an merge the result in a object.
Assume I have three arrays
var users = [
{ name: "A", type: 2, level: 1 },
{ name: "B", type: 1, level: 2 }
]
var types = [
{ description: "Type 1", id: 1 },
{ description: "Type 2", id: 2 }
]
var levels = [
{ description: "Level 1", id: 1 },
{ description: "Level 2", id: 1 }
]
I want to have following result:
var users = [
{ name: "A", type: 2, level: 1, levelDescription: "Level 1", typeDescription: "Type 2" },
{ name: "B", type: 1, level: 2, levelDescription: "Level 2", typeDescription: "Type 1" }
]
I know I can achieve it like that
var usersObservable = RX.Observable.fromArray(users);
var typesObservable = Rx.Observable.fromArray(types);
var levelsOBservable = Rx.Observable.fromArray(levels);
var uiUsers= [];// not really needed because I will use the same users array again.
usersObservable.map(function(user) {
typesObservable.filter(function(type) {
return type.id == user.type;
}).subscribeOnNext(function(userType) {
user.typeDescription = userType.description;
});
return user;
}).map(function(user) {
levelsOBservable.filter(function(level) {
return level.id == user.levelId;
}).subscribeOnNext(function(level) {
user.levelDescription = level.description;
});
return user;
})
.subscribeOnNext(function(user) {
uiUsers.push(user);
})
I would like to have a solution without nested Observables.
Thanks.
I am not sure why you are using Rx at all for this problem. You have data in space (i.e. arrays), not data over time (i.e. an observable sequence). But you force these arrays into Rx to then create a very complicated solution.
I think you are looking for something like the answer here https://stackoverflow.com/a/17500836/393615 where you would join the source array types. In your case you just "inner-join" twice to combine all three data sets.
You can archive this by using the switchMap operator that combines the result of a filtered stream with the latest value of the original stream and uses a projection function to merge the results into a single object. This can be generalised in your example such that you can use a generic higher order function in both cases. See fiddle.
Full code (ES2015, RxJS5):
const users = [
{ name: "A", type: 2, level: 1 },
{ name: "B", type: 1, level: 2 }
];
const types = [
{ description: "Type 1", id: 1 },
{ description: "Type 2", id: 2 }
];
const levels = [
{ description: "Level 1", id: 1 },
{ description: "Level 2", id: 2 }
];
const users$ = Rx.Observable.from(users);
const types$ = Rx.Observable.from(types);
const levels$ = Rx.Observable.from(levels);
function join(s$, sourceProperty, targetProperty, streamProperty) {
return function(initObj) {
const stream$ = s$.filter(x => x.id === initObj[sourceProperty]);
return Rx.Observable.combineLatest(
Rx.Observable.of(initObj),
stream$,
(obj, streamObj) => {
const prop = streamObj[streamProperty];
return Object.assign({}, obj, { [targetProperty]: prop });
}
);
};
}
users$
.switchMap(join(types$, 'type', 'typeDescription', 'description'))
.switchMap(join(levels$, 'level', 'levelDescription', 'description'))
.subscribe(x => console.log(x));

Looping through data structure in coffeescript

I have the following data structure:
{
data: [
{
id: 5,
name: 'ItemOne'
},
{
id: 14,
name: 'ItemTwo'
},
{
id: 15,
name: 'ItemThree'
}
]
}
And I want to loop through it, but I'm struggling. I've tried:
for result,value of results
console.log results
item = 0
message = "Component: " + value[item]['name'] + " Status: " + value[item]['status']
output.push message
item++
But it only return one result. I'm obviously miles off, but what do I need to do?
You should iterate through .data. Here is a fully working example: http://jsfiddle.net/hd4ru1kf/5/
Originally in the question there was also a problem with the data notation
You can benefit from learning the CoffeeScript JSON notation here.
kids =
brother:
name: "Max"
age: 11
sister:
name: "Ida"
age: 9
Compiles to:
kids = {
brother: {
name: "Max",
age: 11
},
sister: {
name: "Ida",
age: 9
}
};
In your example you have , characters that are invalid and the whole JSON structure is way off. You have also nested the JSON awkwardly, perhaps you don't want that? Instead I think this is the working version you are looking for (you can use http://coffeescript.org/ to check it out):
data:
[
{
id: 1
name: "Item one"
}
{
id: 2
name: "Item two"
}
{
id: 3
name: "Item three"
}
]

Kendo DataSource: How to define "Computed" Properties for data read from remote odata source

Situation:
kendo DataSource
var ordersDataSource = new kendo.data.DataSource({
type: "odata",
transport: {
read: {
url: "http://localhost/odata.svc/Orders?$expand=OrderDetails"
}
},
schema: {
type: "json",
data: function(response){
return response.value;
}
total: function(response){
return response['odata.count'];
}
},
serverPaging: true,
serverFiltering: true,
serverSorting: true
})
the json data read from the odata source is like:
{
odata.metadata: "xxxx",
odata.count: "5",
value: [
{
OrderId: 1,
OrderedDate: "2013-02-20",
OrderInfoA: "Info A",
OrderInfoB: "Info B"
OrderDetails: [
{
OrderDetailId: 6,
OrderDetailInfoC: "Info C",
OrderDetailInfoD: "Info D"
},
{
//Another OrderDetail's data
}
]
},
{
// Another Order's data
}
]
}
Question 1:
1.If I wanna define a "computed" property: OrderedDateRelative, which should be the number of days between Today(2013-02-25) and the Day the Order was Created(2013-02-20), Like: "5 days ago", HOW can i achieve this in the client side?
Answer to Question1: http://jsbin.com/ojomul/7/edit
Question 2 --UPDATE--
2.Every Order has its Nested Property OrderDetails, so is it possible to define a Calculated Field for the Nested OrderDetails Property? Like: OrderDetailInfoCAndD for each OrderDetail, and the value should be something like: OrderDetailInfoC + OrderDetailInfoD, which is "Info C Info D"?
Thanks,
dean
You can create a calculated field by specifying the model of the data source:
dataSource = new kendo.data.DataSource({
data: [
{ first: "John", last: "Doe" },
{ first: "Jane", last: "Doe" }
],
schema: {
model: {
// Calculated field
fullName: function() {
return this.get("first") + " " + this.get("last");
}
}
}
});
Here is a live demo: http://jsbin.com/ojomul/1/edit
Here is a way to use calculated field in Kendo Grid.
var crudServiceBaseUrl = "http://demos.telerik.com/kendo-ui/service",
dataSource = new kendo.data.DataSource({
transport: {
read: {
url: crudServiceBaseUrl + "/Products",
dataType: "jsonp"
}
},
pageSize: 20,
schema: {
model: {
total: function (item) {
return this.UnitPrice * this.UnitsInStock;
}
}
}
});
$("#grid").kendoGrid({
dataSource: dataSource,
pageable: true,
height: 550,
sortable: true,
filterable: true,
toolbar: ["create"],
columns: [
{ field: "UnitPrice", title: "Unit Price"},
{ field: "UnitsInStock", title: "Units In Stock", width: "120px" },
{ field: "total()", title: "Total" }]
});
Below an example to use it in a grid. It can then also sort the column.
$("#grid").kendoGrid({
dataSource: {
data: [
{ first: "John", last: "Doe" },
{ first: "Jane", last: "Doe" }
],
schema: {
model: {
// Calculated field
fullName: function() {
return this.first + " " + this.last;
},
fields: {
first: { type: "string" },
last: { type: "string" }
}
}
}
},
columns: [
{
// Trigger function of the Calculated field
field: "fullName()",
title: "Fullname"
},
{
field: "first",
title: "firstname"
}
]
});