Sort ruby middleman array into 3 columns, content in placed in order to display LTR - ruby

I am using middleman and have a specific structure that I want my articles to fall into:
.row>
.col-1>article 1, article 4...
.col-2>article 2, article 5...
.col-3>article 3, article 6...
The goal is that the articles read left-to-right, however are stacked in their columns so there is now additional row class that is needed. I have these articles enclosed in a visual card, and want to stack them which is why I have this strange problem to solve.
My question is what is the cleanest ruby way to sort the array into this format? The goal is to use it in a structure like this and be able to account for any number of columns, n.
.row
- page_articles.someProcess(n).each_split(n) do | col |
.column-class
- col.each do | art |
...

Verbatim from group_by doc:
(1..6).group_by{ |i| i%3 }
#=> {0=>[3, 6], 1=>[1, 4], 2=>[2, 5]}
specifically, use the flatten values
page_articles.group_by.with_index{ |a,i| i%3 }.values.flatten(1)

Related

Setting order method in Sicstus prolog Samsort

I am trying to sort a list of lists such as Books=[[5,1,science,24,3,2018],[6,1,math,24,3,2019],[4,2,science,24,5,2019],[6,2,science,23,3,2019],[3,1,math,24,3,2020]]. I want to order this list based on the 5th value of each element. I tried to use
samsort(sortDateBooks, Books, Output).
sortDateBooks(Book1,Book2):-nth0(5,Book1, Date1),nth0(5,Book2, Date2), Date1<Date2.
The output variable is never filled with data and the original list is also not changed.
I feel that I am not declaring de order predicate properly but can't find any examples.
Thank you for your help.
Well, I noticed I had forgotten to import the samsort library and because of the way it is used no error would be shown. Many thanks to #Reema Q Khan that provided a very usefull workaround and a easy explanation.
I am not sure if this is what you want to do, if yes, then this may give you some hints:
1. Here collect dates will act as findall. It will search for all the years and put them in a list e.g. [2019,2018,2019,2019,2020].
2. sortBook(Sorted) predicate first finds all the Years using collectdates predicate, then sorts them. Notice that in sort I've used #=<, this will not remove any repeated values. You will get [2018,2019,2019,2019,2020].
3. s predicate simply takes each year, searches for the information and puts it in a List.
s predicate will take each year and check through each book, so this may lead to extras. append is used to decrease extra brackets, set predicate simply removes duplicates if any.
sortBook(Sorted):-
Book=[[6,2,science,23,3,2019],[5,1,science,24,3,2018],[6,1,math,24,3,2019],[4,2,science,24,5,2019]
,[3,1,math,24,3,2020]],
collectdates(Book,Clist),
sort(0, #=<, Clist, SList),
s(SList,Book,Sorted1),append(Sorted1,Sorted2),set(Sorted2,Sorted).
collectdates([],[]).
collectdates([H|T],[Last|List]):-
last(H,Last),
collectdates(T,List).
s([],_,[]).
s([H|T],[B|L],[W|List]):-
sortBook1(H,[B|L],W),
s(T,[B|L],List).
sortBook1(_,[],[]).
sortBook1(H,[B|L],[B|List]):-
member(H,B),
sortBook1(H,L,List).
sortBook1(H,[B|L],List):-
\+member(H,B),
sortBook1(H,L,List).
set([],[]).
set([H|T],[H|T2]):-
subtract(T,[H],T3),
set(T3,T2).
Example:
?-sortBook(Sorted).
Sorted = [[5, 1, science, 24, 3, 2018], [6, 2, science, 23, 3, 2019], [6, 1, math, 24, 3, 2019], [4, 2, science, 24, 5, 2019], [3, 1, math, 24, 3, 2020]]
false

Can I count on partition preserving order?

Say I have a sorted Array, such as this:
myArray = [1, 2, 3, 4, 5, 6]
Suppose I call Enumerable#partition on it:
p myArray.partition(&:odd?)
Must the output always be the following?
[[1, 3, 5], [2, 4, 6]]
The documentation doesn't state this; this is what it says:
partition { |obj| block } → [ true_array, false_array ]
partition → an_enumerator
Returns two arrays, the first containing the elements of enum for which the block evaluates to true, the second containing the rest.
If no block is given, an enumerator is returned instead.
But it seems logical to assume partition works this way.
Through testing Matz's interpreter, it appears to be the case that the output works like this, and it makes full sense for it to be like this. However, can I count on partition working this way regardless of the Ruby version or interpreter?
Note: I made implementation-agnostic because I couldn't find any other tag that describes my concern. Feel free to change the tag to something better if you know about it.
No, you can't rely on the order. The reason is parallelism.
A traditional serial implementation of partition would loop through each element of the array evaluating the block one at a time in order. As each call to odd returns, it's immediately pushed into the appropriate true or false array.
Now imagine an implementation which takes advantage of multiple CPU cores. It still iterates through the array in order, but each call to odd can return out of order. odd(myArray[2]) might return before odd(myArray[0]) resulting in [[3, 1, 5], [2, 4, 6]].
List processing idioms such as partition which run a list through a function (most of Enumerable) benefit greatly from parallel processing, and most computers these days have multiple cores. I wouldn't be surprised if a future Ruby implementation took advantage of this. The writers of the API documentation for Enumerable likely carefully omitted any mention of process ordering to leave this optimization possibility open.
The documentation makes no explicit mention of this, but judging from the official code, it does retain ordering:
static VALUE
partition_i(RB_BLOCK_CALL_FUNC_ARGLIST(i, arys))
{
struct MEMO *memo = MEMO_CAST(arys);
VALUE ary;
ENUM_WANT_SVALUE();
if (RTEST(enum_yield(argc, i))) {
ary = memo->v1;
}
else {
ary = memo->v2;
}
rb_ary_push(ary, i);
return Qnil;
}
This code gets called from the public interface.
Essentially, the ordering in which your enumerable emits objects gets retained with the above logic.

How to custom sort with ruby

I've got an array of objects which I pull from the database. But I can sort them only in ascending or descending order from database, however I need them in custom order.
Let's say I have an array of objects from db :
arr = [obj1,obj2,obj3]
where obj1 has id 1, obj2 has id 2 and obj3 has id 3
but my sort order would be 3,1,2 or I'd have some array of ids which would dictate the order i.e [3,1,2]
So the order of custom sorting would be :
arr = [obj3,obj1,obj2]
I've tried :
arr.sort_by{|a,b| [3,1,2]}
I've been reading some tutorials and links about sorting and it's mostly simple sorting. So how would one achieve the custom sorting described above?
You're close. [3,1,2] specifies an ordering, but it doesn't tell the block how to relate it to your objects. You want something like:
arr.sort_by {|obj| [3,1,2].index(obj.id) }
So the comparison will order your objects sequentially by the position of their id in the array.
Or, to use the more explicit sort (which you seem to have sort_by slightly confused with):
arr.sort do |a,b|
ordering = [3,1,2]
ordering.index(a.id) <=> ordering.index(b.id)
end
This is like #Chuck's answer, but with O(n log n) performance.
# the fixed ordering
ordering = [3, 1, 2]
# a map from the object to its position in the ordering
ordering_index = Hash[ordering.map(&:id).each_with_index.to_a]
# a fast version of the block
arr.sort_by{|obj| ordering_index[obj.id]}

Understanding Ruby array sorting syntax

I really don't understand the following sorting method:
books = ["Charlie and the Chocolate Factory", "War and Peace", "Utopia", "A Brief History of Time", "A Wrinkle in Time"]
books.sort! { |firstBook, secondBook| firstBook <=> secondBook }
How does the this work? In the ruby books, they had one parameter for example |x| represent each of the values in the array. If there is more than one parameter (firstBook and secondBook in this example) what does it represent??
Thank you!
The <=> operator returns the result of a comparison.
So "a" <=> "b" returns -1, "b" <=> "a" returns 1, and "a" <=> "a" returns 0.
That's how sort is able to determine the order of elements.
Array#sort (and sort!) called without a block will do comparisons with <=>, so the block is redundant. These all accomplish the same thing:
books.sort!
books.sort_by!{|x| x}
books.sort!{|firstBook, secondBook| firstBook <=> secondBook}
Since you are not overriding the default behavior, the second and third forms are needlessly complicated.
So how does this all work?
The first form sorts the array by using some sorting algorithm -- it's not relevant which one -- which needs to be able to compare two elements to decide which comes first. (More on this below.) It automatically, behind the scenes, follows the same logic as the third line above.
The middle form lets you choose what to sort on. For example: instead of, for each item, just sorting on that item (which is the default), you can sort on that item's length:
books.sort_by!{|title| title.length}
Then books is sorted from shortest title to longest title. If all you are doing is calling a method on each item, there's another shortcut available. This does the same thing:
books.sort_by!(&:length)
In the final form, you have control over the comparison itself. For example, you could sort backwards:
books.sort!{|first, second| second <=> first}
Why does sort need two items passed into the block, and what do they represent?
Array#sort (and sort!) with a block is how you override the comparison step of sorting. Comparison has to happen at some point during a sort in order to figure out what order to put things in. You don't need to override the comparison in most cases, but if you do, this is the form that allows that, so it needs two items passed into the block: the two items that need to be compared right now. Let's look at an example in action:
[4, 3, 2, 1].sort{|x, y| puts "#{x}, #{y}"; x <=> y}
This outputs:
4, 2
2, 1
3, 2
3, 4
This shows us that in this case, sort compared 4 and 2, then 2 and 1, then 3 and 2, and then finally 3 and 4, in order to sort the array. The precise details are irrelevant to this discussion and depend on the sorting algorithm being used, but again, all sorting algorithms need to be able to compare items in order to sort.
The block given inside {} is passed as a comparing function for method sort. |a, b| tells us that this comparing function takes 2 parameters (which is expected number of arguments since we need to compare).
This block is executed for each element in array but if we need one more argument we take next element after this.
See http://ruby-doc.org/core-2.0/Array.html#method-i-sort for an explanation. As for a single-parameter method referred to in your books, I can only guess you were looking at sort_by. Can you give an example?

Ruby: What is a simple way of searching for certain criteria in an array?

I have an array which I want to make sure all the numbers are between 1 and 6. Here is my array:
guess = [2, 5, 6, 8]
Or something like that. The user inputs the sequence. Anyway, I want a way to check it, and if the numbers aren't all between 1 and 6, it won't break out of the loop. And also could it please be simple!
guess.all?{|i| (1..6).include?(i)}
guess.count{|i| i.between?(1,6)} == guess.size

Resources