Shorten an array or collection with an array of fields - backbone.js

Scenario:
you have an array,
you have an array of some ids (eg: [1,3]),
you want to get a shortened array.
I cannot find how to do so if not in the lengthy way:
_.filter(... function (id) { return id==1 || id==3 })
Question: does such someMethod1 exist in underscore.js?
var frdsArr =
[
{id: 1, name: 'moe', age: 40},
{id: 2, name: 'larry', age: 50},
{id: 3, name: 'curly', age: 60}
];
var goodFrdsArr = _.someMethod1( frdsArr, 'id', [1, 3] );
/*
goodFrdsArr is [
{id: 1, name: 'moe', age: 40},
{id: 3, name: 'curly', age: 60}
];
*/
The same question with backbone.js: what about someMethod2?
var Friend = Backbone.Model.extend({});
var FriendsCollection = Backbone.Collection.extend({
model: Friend
});
var friendsCollection = new FriendsCollection( frdsArr );
var goodFriendsCollection = friendsCollection.someMethod2( 'id', [1,3] );
/*
goodFriendsCollection contains 2 instances of Friend Models
*/

Once you have found a suitable function, you can extend Underscore with _.mixin to simplify later calls. For example, you could create _.restrict to match your _.someMethod1 signature:
_.mixin({
// filter a list on an attribute having to match a list of values
// _.indexOf accepts an optional isSorted argument so let's pass it
restrict: function(list, attr, values, isSorted) {
return _.filter(list, function(obj) {
return _.indexOf(values, obj[attr], isSorted) !== -1;
});
}
});
var goodFrdsArr = _.restrict(frdsArr, 'id', [1, 3]);
See http://jsfiddle.net/nikoshr/cf0qs5gh/ for a demo
With this setup, you can modify Backbone.Collection's prototype to give all your collections this new capacity (more or less taken from the Backbone source code):
Backbone.Collection.prototype.restrict = function() {
var args = [].slice.call(arguments);
args.unshift(this.models);
return _.restrict.apply(_, args);
};
var friendsCollection = new Backbone.Collection(frdsArr);
var goodfriends = c.restrict('id', [1, 3]); //an array with 2 models
http://jsfiddle.net/nikoshr/cf0qs5gh/1/

var frdsArr =
[
{id: 1, name: 'moe', age: 40},
{id: 2, name: 'larry', age: 50},
{id: 3, name: 'curly', age: 60}
];
var filteredIDs = [1,3];
var filteredFrnds = _.filter(frdsArr, function(frnd){
return _.contains(filteredIDs, frnd.id);
})
console.log(filteredFrnds);
Make use of filter and contains
FIDDLE

Related

How to find sum of values of objects in array in dart?

I have an array that is like following:
[{name: Cibo, quantity: 3},
{name: Cibo, quantity: 2},
{name: Invia Regalo, quantity: 3},
{name: Invia Regalo, quantity: 1}]
How can I find the total quantity for these objects by combining the same names?
So output would look like:
[
{name: Invia Regalo, quantity: 4},
{name: Cibo, quantity: 5},
]
I have tried something like this, but does not work in Dart.
var categoryTotal = [];
category.forEach((category) {
print(category);
var categ =
categoryTotal.firstWhere((cat) => cat['name'] == category['name']);
print("Category is $categ");
if (categ != null) {
categ['quantity'] += category['quantity'];
} else {
categoryTotal.add(category);
}
});
print(categoryTotal);
I will in general not recommend the use of maps maps to handle objects that contains different types of values. Instead, use classes. It makes it a lot easier to write type safe code.
Also, I will not recommend using the .forEach() method when you have multiple lines of code since it can make it difficult to read. Instead, use a for-each loop.
I have made the following solution to handle your list of maps. The sumMap is for making the code more efficient by using a Map to handle the sums of quantity. The result are then created based on sumMap:
void main() {
final array = [
{'name': 'Cibo', 'quantity': 3},
{'name': 'Cibo', 'quantity': 2},
{'name': 'Invia Regalo', 'quantity': 3},
{'name': 'Invia Regalo', 'quantity': 1},
];
final sumMap = <String, int>{};
for (final map in array) {
sumMap.update(
map['name']! as String,
(sum) => sum + (map['quantity']! as int),
ifAbsent: () => map['quantity']! as int,
);
}
final result = [
for (final entry in sumMap.entries)
{'name': entry.key, 'quantity': entry.value}
];
print(result);
// [{name: Cibo, quantity: 5}, {name: Invia Regalo, quantity: 4}]
}
You need to add orElse: () => null to avoid exeption. So, final code would look like this:
var categoryTotal = [];
category.forEach((category) {
var categ = categoryTotal.firstWhere(
(cat) => cat['name'] == category['name'],
orElse: () => null,
);
if (categ != null) {
categ['quantity'] += category['quantity'];
} else {
categoryTotal.add(category);
}
});
print(categoryTotal);

How to find objects with the same property values in an Array of Objects in typescript?

I have an array of objects
var myArray = [
{id: 1, name: 'Foo Bar', email: 'foo#bar.com'},
{id: 2, name: 'Bar Foo', email: 'bar#foo.com'},
{id: 3, name: 'Joe Ocean', email: 'joe#ocean.com'},
{id: 3, name: 'Jenny Block', email: 'foo#bar.com'},
];
I am expecting the following output:
commonIdsObjects = [
{id: 3, name: 'Joe Ocean', email: 'joe#ocean.com'},
{id: 3, name: 'Jenny Block', email: 'foo#bar.com'},
]
I assume that you want the output to be a single array containing all the duplicate entries, even if some of those entries have different ids. For example, if you had added {id: 2, name: 'Fishy Joe', email: 'com#foo.bar'} to myArray, the resulting commonIdsObjects would be an array of four items: two for id: 2 and two for id: 3. If this is not what you want then you should take care to specify exactly the expected behavior.
Anyway, assuming you have a type corresponding to the elements of myArray, like this:
type Elem = typeof myArray[number];
And assuming your target runtime has access to the Object.values() and Array.prototype.flat() methods, then you can write
const commonIdsObjects = Object.values(
myArray.reduce<{ [k: number]: Elem[] }>(
(a, v) => ((a[v.id] || (a[v.id] = [])).push(v), a), {}
)
).filter(c => c.length > 1).flat(1);
What we're doing is using myArray.reduce() to build an object whose keys correspond to your elements' id values, and whose values are arrays of elements with those id. We convert this object into an array of arrays of elements, keep only those whose lengths are more than one (i.e., any id with more than one element corresponding to it), and flatten into a single array.
This will produce the desired result:
console.log(JSON.stringify(commonIdsObjects));
// [{"id":3,"name":"Joe Ocean","email":"joe#ocean.com"},
// {"id":3,"name":"Jenny Block","email":"foo#bar.com"}]
If you don't have access to Object.values() and [].flat() you can use Object.keys() and [].reduce() instead:
type ElemsById = { [k: string]: Elem[] }
const commonIdsObjects2 = ((o: ElemsById) => Object.keys(o).map(k => o[k]))(
myArray.reduce<ElemsById>(
(a, v) => ((a[v.id] || (a[v.id] = [])).push(v), a), {}))
.filter(c => c.length > 1).reduce<Elem[]>((a, v) => (a.push(...v), a), []);
console.log(JSON.stringify(commonIdsObjects2)); // same
which is essentially the same algorithm. Or you could do this algorithm the purely-imperative-programming way with various for loops:
const elemsById: ElemsById = {};
for (let v of myArray) {
if (!elemsById[v.id]) {
elemsById[v.id] = []
}
elemsById[v.id].push(v);
}
const commonIdsObjects3: Elem[] = []
for (let k in elemsById) {
if (elemsById[k].length <= 1) {
continue;
}
for (let v of elemsById[k]) {
commonIdsObjects3.push(v);
}
}
console.log(JSON.stringify(commonIdsObjects3)); // same
Okay, hope that helps; good luck!
Playground link to code
var myArray = [
{ id: 1, name: "Foo Bar", email: "foo#bar.com" },
{ id: 2, name: "Bar Foo", email: "bar#foo.com" },
{ id: 3, name: "Joe Ocean", email: "joe#ocean.com" },
{ id: 3, name: "Jenny Block", email: "foo#bar.com" }];
const commonIdsObjects = myArray.filter(x => x.id === 3);
console.log(commonIdsObjects);

Using find to filter array with two arguments

I'm trying to filter my array of objects passing two parameters but it's not working... My array contain an object with the values that I'm passing on parameters but the result is empty
const item = this.lista.find(i => i.number === rule.number && i.name === rule.name);
I also tried to use "filter" but same problem...
const item = this.lista.filter(i => i.number === rule.number).filter(i =>
i.name === rule.name);
Here is my full array:
this.lista= [
{number: 0, name: 'jose'},
{number: 2, name: 'maria'},
{number: 3, name: 'martha'},
{number: 4, name: 'ana'},
{number: 4, name: 'petter'},
];
And this is the rule object:
rule = new Rule();
rule.number = 4;
rule.name = 'ana';
There's a best way to do this?
I'm not sure what the problem is in your code but I've reproduced a simple example of your code and it works just as expected.
const rule = {};
rule.number = 4;
rule.name = 'ana';
const lista = [{
number: 0,
name: 'jose'
},
{
number: 2,
name: 'maria'
},
{
number: 3,
name: 'martha'
},
{
number: 4,
name: 'ana'
},
{
number: 4,
name: 'petter'
},
];
const item = lista.find(i => i.number === rule.number && i.name === rule.name);
console.log(item);

Get only values from the array of array using angular js

I got an array from database as
[
{id:
{unitno: 'abc'},
amount: 100},
{id:
{unitno: 'xyz'},
amount: 150}
]
Now my required answer is that should be in the following format,
[["abc",100],
["xyz",150]]
But after some coding I got an array of Array as shown below in the console
[0:[0:"abc",1:100]
1:[0:"xyz",1:150]]
Before question down / marking duplicate please read my requirement, and if its there then mark it and please post that link as per my required solution so i can get my solution from there
So any help will be great help....
You can do like this:
data = [
{id:
{unitno: 'abc'},
amount: 100},
{id:
{unitno: 'xyz'},
amount: 150}
]
var array =[]
data.forEach(function(item){
var tmpArray = []
tmpArray.push(item.id.unitno,item.amount)
array.push(tmpArray)
})
Now you will get your required data in the array.
I don't know how you got this below code, but that's invalid Array
[0:[0:"abc",1:100] 1:[0:"xyz",1:150]]
For your desired output you can do it with JavaScript, no need angular. Just run a simple for loop.
var temp1 = [{
id: {
unitno: 'abc'
},
amount: 100
}, {
id: {
unitno: 'xyz'
},
amount: 150
}];
var eee = [];
temp1.forEach(function(el) {
eee.push([el.id.unitno, el.amount])
});
console.log('eee:', eee);
Hope this is what you needed.
var arr = [{
id : { unitno: 'abc' },
amount: 100
},{
id : { unitno: 'xyz' },
amount: 150
}];
var result = [];
for (var i = 0; i < arr.length; i++) {
var newArray = [];
newArray.push( arr[i]["id"]["unitno"] );
newArray.push( arr[i]["amount"] );
result.push( newArray );
}
console.log( result );

AngularJS: orderBy - string & array are not the same

I have an array of users:
$scope.users = [
{name: 'Anh', age: 10},
{name: 'Ánh', age: 10},
{name: 'Ba' , age: 10}
]
When i use orderBy:'name' the result is:
Anh
Ánh
Ba
but when i use multiple fields orderBy:['name','age'] the result is different:
Anh
Ba
Ánh
Waiting for your help!
try this..
var app = angular.module('filterSample', []);
app.controller('filterCtrl', function ($scope) {
$scope.data = {
messages: ['first', 'second', '3rd', 'fourth', 'fifth']
}
$scope.startsWith = function (actual, expected) {
var lowerStr = (actual + "").toLowerCase();
return lowerStr.indexOf(expected.toLowerCase()) === 0;
}
});
and html as
<ul border="1px" ng-repeat="msg in data.messages | filter:search:startsWith">
<li>{{msg}}</li>
</ul>
or check on this plunkr-http://plnkr.co/edit/gcVYfZXTqsDU1Z7REU2I?p=preview

Resources