Multi level list with links in Meteor - meteor

I have a collection with fields groupNumber and number:
groupNumber, number
=================
1, 1
1, 2
1, 3
1, 4
2, 1
2, 2
2, 3
2, 8
3, 4
3, 5
...
I can print the entire collection with
{{#each numbers}}
<tr>
<td>{{groupNumber}}</td>
<td>{{number}}</td>
</tr>
{{/each}}
but I need it to be links instead. So at the first page I need to see a list of the group numbers (1, 2, 3, ...) and when I've clicked one of the groups, I see the numbers belonging to this group.
I could easily achieve this if I had groupNumber and number split in two different collections and use iron-router to navigate between list of groups and list of numbers belonging to group. But how can I get this with the two fields in the same collection?

Why don't you "group" your groups manually?
At first get all your group numbers.
var allValues = YourCollection.find().fetch();
var uniqueGroups = _.union(_.pluck(allValues, 'groupNumber')) //outputs [1,2,3]
After that, simple route will do the job:
Router.route('/group/:groupNumber?', function () {
this.render('your_template', {
data: function () {
if(this.params.hasOwnProperty('groupNumber')){
return {
groupNumber: this.params.groupNumber
}
} else {
var allValues = YourCollection.find().fetch();
var uniqueGroups = _.union(_.pluck(allValues, 'groupNumber'))
return {
groups: uniqueGroups
}
}
}
});
});
Then in your_template check, if you have groupNumber, show all numbers
by YourCollection.find({groupNumber: this.groupNumber})
if not, then just render this.groups:
{{#each groups}}
{{this}}
{{/each}}

Related

Please how do i achieve the following using ramda

I have a random array of numbers 1 to five occurring in ramdom sometimes [1,1,1,1,2,2] etc. I am tasked with finding the value with highest occurrence all the the time regardless. I achieved that in javascript like below using a library called ramda here . After reading the documentation, i went with a solution like below.
// filter out duplication in array that way you can get the uniq represented numbers
const uniqueItems = R.uniq(params);
// use the unique numbers as keys and create a new array of object
const mappedItemsWithRepresentations = map((a) => ({ color: a, rep: params.filter(b => b === a).length }), uniqueItems);
// and then finally, select the item with highest rep and return it key
const maxRepItem = mappedItemsWithRepresentations.reduce((acc, curr) => acc.rep > curr.rep ? acc : curr, []);
return maxRepItem.key; // gives me the correct value i need
However, reading through more in the documentation and going through the example here, i realised there is a way i can combine the logic above and simply with ramda. I tried numerous attempt possible and the closest i could get are below.
const getMaxRep = curry(pipe(uniq, map((a) => ({ color: a, rep: filter(b => b === a).length })), pipe(max(pathEq("rep")), tap(console.log))));
console.log("Max Rep here", getMaxRep(params));
I also tried utilising the reduced feature here, all to no avail. Please how do i arrange achieve that ? Any help will be appreciated.
Ramda has R.countBy to get the number of occurrences. You can convert the resulting object of country to pairs [value, count], and then reduce it to find the pair with the highest count:
const { pipe, countBy, identity, toPairs, reduce, maxBy, last, head } = R
const fn = pipe(
countBy(identity), // count the occurrences
toPairs, // convert to pairs of [value, count]
reduce(maxBy(last), [0, 0]), // reduce to find the maximum occurrence
head, // get the actual value
Number, // convert back to an number
)
const arr = [1,1,1,1,2,2]
const result = fn(arr)
console.log(result)
<script src="https://cdnjs.cloudflare.com/ajax/libs/ramda/0.27.0/ramda.js"></script>
A slight variation on this idea that collects values with the same count to an array. This will handle cases in which the frequency of several items is identical:
const { pipe, countBy, identity, toPairs, invert, reduce, maxBy, last, head, map } = R
const fn = pipe(
countBy(identity), // count the occurrences
invert, // combine all values with the same count
toPairs, // convert to pairs of [value, count]
reduce(maxBy(head), [0, 0]), // reduce to find the maximum occurrence
last, // get the actual values
map(Number), // convert back to numbers
)
const arr = [1,1,1,1,2,2,3,3,3,3]
const result = fn(arr)
console.log(result)
<script src="https://cdnjs.cloudflare.com/ajax/libs/ramda/0.27.0/ramda.js"></script>
nice use case, try this:
const maxReduce = reduce(maxBy(last), [0,0])
const getMaxRep = pipe(countBy(identity), toPairs, maxReduce, head)
console.log(getMaxRep([1,1,1,1,2,2]))
countBy is a really nice start, sadly Ramda don't support reduce for object but we can convert to an array of arrays using toPairs function and finish the work.
It's not entirely clear to me what it is you're asking for.
But it might be something like this:
const maxRep = pipe (
countBy (identity),
toPairs,
map (zipObj(['color', 'rep'])),
reduce (maxBy (prop ('rep')), {rep: -Infinity}),
)
const params = [1, 2, 3, 4, 2, 3, 5, 2, 3, 2, 1, 1, 4, 5, 5, 3, 2, 5, 1, 5, 2]
console .log (
maxRep (params)
)
<script src="//cdnjs.cloudflare.com/ajax/libs/ramda/0.27.0/ramda.js"></script>
<script> const {pipe, countBy, identity, toPairs, map, zipObj, reduce, maxBy, prop} = R </script>
We start with a list of values drawn from {1, 2, 3, 4, 5}, occuring in some random, multiply-occuring order.
With countBy(identity) we change the original list into something like
{"1": 4, "2": 6, "3": 4, "4": 2, "5": 5}
with the counts associated with each entry.
toPairs formats that as an array like
[["1", 4], ["2", 6], ["3", 4], ["4", 2], ["5", 5]]
(You could also use Object.entries here.)
Then by calling map (zipObj (['color', 'rep'])), we turn this into
[{"color": "1", "rep": 4}, {"color": "2", "rep": 6}, ...]
Finally, we reduce the result, using maxBy (prop ('rep')), which chooses the one with the maximum rep value. For the initial value to the max call, we create a dummy object, {rep: -Infinity} that will compare less than any in your list.
If you wanted to also keep that final intermediate structure, you could rename that function to makeReps, dropping off the last function in the pipeline, and then making a new maxRep out of it.
Then you could call
const reps = makeResps (params)
const maxVal = maxRep (reps)
and use both.
But all this presupposes that the value with color and rep properties is what you need. If you just need the count then the other solutions already here handle that fine.

Coffee Script Array, Object

# String of Markdown in DB
beforeMark = #content
# Render string of markdown to html string
afterMark = marked(beforeMark)
# Parse the html to HTML to extract 0, 2, 4th children node (elements)
finalMark = $.parseHTML(afterMark)
# Help needed HERE
# Get 0 2 4th elements if they exist.
# ex) if array has 4 keys, return 0, 2th
# if array has 7 keys, return 0, 2, 4th
# if array has 3 keys, return 0, 2th
# if array has 1 key, return 0th
stringMark = $(finalMark[0]).prop('outerHTML') + $(finalMark[2]).prop('outerHTML') + $(finalMark[2]).prop('outerHTML')
I have the above coffeescript I wrote to truncate a markdown string into html of 3 elements.
I need the last part to be more efficient and proper so that it returns the 0, 2, 4th keys of arrays but only if they exist.
I am new to coffee and I need help!!
If I understand the problem correctly, I believe you want something like this:
stringMark = ''
for data, index in finalMark when index in [0, 2, 4]
stringMark += data.prop 'outerHTML'
Or if you like a little code golf:
stringMark = (v.prop 'outerHTML' for v, i in finalMark when i in [0, 2, 4]).join ''

Computer science map and exclude

I have an array with some values:
[1, 2, 3, 4]
I'd like to make a new array that contains mapped version of the items in the array above, but only add them to the new array if they pass a truth test.
A combination of map and filter?
[1, 2, 3, 4].mapFilter(function(n) { if (n > 2) return n * 3 })
What is this called?
This is map composed with filter. It doesn't need a name.
map (*3) . filter (>2)

Converting Array of Arrays to Backbone Collection of Models

new to Backbone and underscore js here.
I have an array of arrays that I want to convert to a collection of models.
So it's like
{ {1, 2, 3, 4}, {5, 6, 7, 8}}
The second level of arrays is what's going into a backbone model. Right now, I have
collection.reset(_.map(results, (indvidualResults) -> new model(individualResults))
Which doesn't work as when I do a console.log(collection.pop) I get a function printed out. I think this is because I'm working with an array of arrays (but I could be wrong). How do I convert the second array into a model and then put that into a collection?
Reshape your raw data to look more like:
[{ first: 1, second: 2, third: 3, fourth: 4 }, { first: 5, second: 6, third: 7, fourth: 8}]
Assuming you have a model and collection defined something like:
var Model = Backbone.Model.extend({});
var Collection = Backbone.Collection.extend({
model: Model
});
Then just pass the array of attribute hashes into the reset method:
var results = [{ first: 1, second: 2, third: 3, fourth: 4 }, { first: 5, second: 6, third: 7, fourth: 8}];
var collection = new Collection();
collection.reset(results);
var model = collection.pop();
console.log(JSON.stringify(model.toJSON());

JavaFX: concatenating sequences

Is there a standard library function or built-in construct to concatenate two sequences in JavaFX?
Here a Sequences.concatenate() function is mentioned, but it is nowhere to be seen in the official API.
Of course one could iterate over each sequence, inserting the values into a new sequence e.g:
function concatenate(seqA: Object[], seqB: Object[]) : Object[] {
for(b in seqB) insert b into seqA;
seqA;
}
..but surely something as basic as concatenation is already defined for us somewhere..
It is very simple, since there cannot be sequence in sequence (it all gets flattened), you can do it like this:
var a = [1, 2];
var b = [3, 4];
// just insert one into another
insert b into a;
// a == [1, 2, 3, 4];
// or create a new seq
a = [b, a];
// a == [3, 4, 1, 2];
Hope that helps.

Resources