List of time stamps not sorting properly - sorting

I have a list of maps each with a key stating the "inserted_at" time in which the items were inserted in my database. I want to sort this list in descending order to show the most recent items first. I thought I had it but when looking closer for some reason the 2nd and 3rd elements should be swapped as well as the 5th and 6 elements.
Any idea?

That's because you are comparing NaiveDateTime in Elixir.
You should use compare method instead of ==, >, <.
e.g, Enum.sort(z, &(NaiveDateTime.compare(&1, &2)==:gt )).

According to the release notes for Elixir v10 below this issue should be fixed natively.
Elixir v1.10 streamlines the sorting functions by introducing both :asc and :desc shortcuts:
iex> Enum.sort(["banana", "apple", "pineapple"], :asc)
["apple", "banana", "pineapple"]
iex> Enum.sort(["banana", "apple", "pineapple"], :desc)
["pineapple", "banana", "apple"]
As well as adding the possibility to pass a module to perform semantic comparisons. For example, to sort dates, one now only needs to pass the Date module or even {:desc, Date} for descending semantical sort:
iex> Enum.sort([~D[2019-12-31], ~D[2020-01-01]], Date)
[~D[2019-12-31], ~D[2020-01-01]]
iex> Enum.sort([~D[2019-12-31], ~D[2020-01-01]], {:desc, Date})
[~D[2020-01-01], ~D[2019-12-31]]
These API improvements make the code more concise and readable and they have also been added to Enum.sort_by, Enum.min_by, Enum.max_by, and friends.

By default a 'map' doesn't provide a 'sorting order'. Not sure what I'm looking at or what language this is in. In Java you would use this type of collection: http://tutorials.jenkov.com/java-collections/sortedmap.html

Related

How to list all continents with the countries gem?

Using the Countries gem https://github.com/hexorx/countries
We have the method:
ISO3166::Country.find_all_countries_by_continent('Europe')
We also have:
ISO3166::Country.countries
But we don't have:
ISO3166::Country.continents
I want to have a 'Filter by continent' select which could be translated using I18n.
Is there an easy way to get all available continents?
As I know (I can be wrong), I think hexorx/countries not give you this possibility natively.
Ps :
I have created an feature request for this if it can make things happen.
You can get all the continents using
ISO3166::Data.cache.map {|_,v| v['continent']}.uniq
#=> ["Asia", "North America", "Africa", "Europe", "South America", "Antarctica", "Australia"]
Due to the fact that this list is highly unlikely to change in the foreseeable future you can just cache these results for your self
ISO3166::CONTINENTS = ISO3166::Data.cache.map {|_,v| v['continent']}.uniq.sort
Then you can just reuse the constant ISO3166::CONTINENTS anywhere you need to.
That being said the i18n_data gem (that is used for translation of countries) does not appear to provide translation for continent names so that would likely fall on your shoulders to maintain.
A Set might make this slightly more efficient too: (although since getting the continents is simply Array traversal and Hash lookup it is already reasonably fast)
ISO3166::CONTINENTS = ISO3166::Data.cache.each_with_object(Set.new) do |(_,v),s|
s.add(v['continent'])
end.sort

How to ignore "stop words" while sorting in MarkLogic?

Is there any way to ignore "stop words" while sorting.
For example:
I have words like
dixit
singla
the marklogic
On sorting in descending order the result should be
singla, the marklogic, dixit
As in the above example the is ignored.
Any way to achieve this?
Update:
Stop word can occur at any place.
for example
the MarkLogic
MarkLogic is the best
the MarkLogic is awesome
while sorting should not consider any stop word in the text.
Above is just a small example to describe the problem.
In actual I am using search:search API.
For sorting, I am using sort-order search options.
The element on which I have to perform sorting is dynamic. There are approx 30-35 elements.
Is there any way to customize the collation at this level like to configure some words (stop words) which will be ignored while sorting.
There is no standard collation URI that is going to do this for you (at least none that I've ever seen). You can do it dynamically, of course, by sorting on the result of a function invocation, but if you want it done efficiently at scale (and available to search:search), then you need to materialize the sortable string into your document. I've often done this as an attribute on the element:
<title sortable="Great Gatsby, The">The Great Gatsby</title>
Then you put a range index on the title/#sortable attribute.
You can also use the "envelope pattern" where materialized metadata like this is maintained in its own section of the document with the original kept in its own section. For things like this, I think it's a bit more elegant to decorate the elements directly, to keep the context.
If I understand your question correctly you're trying to get rid of the definite article when sorting your result-set.
In order to do this you need to use some additional functions and create a 'sort' criteria. My solution would look like this (I'm also including some sample documents so that you can test this just by copy-pasting):
(:
xdmp:document-insert("/peter.xml", <person><firstName>Peter</firstName><lastName>O'Toole</lastName><age>60</age></person>);
xdmp:document-insert("/john.xml", <person><firstName>John</firstName><lastName>Adams</lastName><age>18</age></person>);
xdmp:document-insert("/simon.xml", <person><firstName>Simon</firstName><lastName>Petrov</lastName><age>22</age></person>);
xdmp:document-insert("/mark.xml", <person><firstName>Mark</firstName><lastName>the Lord</lastName><age>25</age></person>);
:)
for $person in /person
let $sort := fn:reverse(fn:tokenize($person/lastName, ' '))[1]
order by $sort
(: return $person :)
return $person/lastName/text()
Notice that now the sort order is going to be
- Adams
- the Lord
- O'Toole
- Petrov
I hope this will help.

Python3 Make tie-breaking lambda sort more pythonic?

As an exercise in python lambdas (just so I can learn how to use them more properly) I gave myself an assignment to sort some strings based on something other than their natural string order.
I scraped apache for version number strings and then came up with a lambda to sort them based on numbers I extracted with regexes. It works, but I think it can be better I just don't know how to improve it so it's more robust.
from lxml import html
import requests
import re
# Send GET request to page and parse it into a list of html links
jmeter_archive_url='https://archive.apache.org/dist/jmeter/binaries/'
jmeter_archive_get=requests.get(url=jmeter_archive_url)
page_tree=html.fromstring(jmeter_archive_get.text)
list_of_links=page_tree.xpath('//a[#href]/text()')
# Filter out all the non-md5s. There are a lot of links, and ultimately
# it's more data than needed for his exercise
jmeter_md5_list=list(filter(lambda x: x.endswith('.tgz.md5'), list_of_links))
# Here's where the 'magic' happens. We use two different regexes to rip the first
# and then the second number out of the string and turn them into integers. We
# then return them in the order we grabbed them, allowing us to tie break.
jmeter_md5_list.sort(key=lambda val: (int(re.search('(\d+)\.\d+', val).group(1)), int(re.search('\d+\.(\d+)', val).group(1))))
print(jmeter_md5_list)
This does have the desired effect, The output is:
['jakarta-jmeter-2.5.1.tgz.md5', 'apache-jmeter-2.6.tgz.md5', 'apache-jmeter-2.7.tgz.md5', 'apache-jmeter-2.8.tgz.md5', 'apache-jmeter-2.9.tgz.md5', 'apache-jmeter-2.10.tgz.md5', 'apache-jmeter-2.11.tgz.md5', 'apache-jmeter-2.12.tgz.md5', 'apache-jmeter-2.13.tgz.md5']
So we can see that the strings are sorted into an order that makes sense. Lowest version first and highest version last. Immediate problems that I see with my solution are two-fold.
First, we have to create two different regexes to get the numbers we want instead of just capturing groups 1 and 2. Mainly because I know there are no multiline lambdas, I don't know how to reuse a single regex object instead of creating a second.
Secondly, this only works as long as the version numbers are two numbers separated by a single period. The first element is 2.5.1, which is sorted into the correct place but the current method wouldn't know how to tie break for 2.5.2, or 2.5.3, or for any string with an arbitrary number of version points.
So it works, but there's got to be a better way to do it. How can I improve this?
This is not a full answer, but it will get you far along the road to one.
The return value of the key function can be a tuple, and tuples sort naturally. You want the output from the key function to be:
((2, 5, 1), 'jakarta-jmeter')
((2, 6), 'apache-jmeter')
etc.
Do note that this is a poor use case for a lambda regardless.
Originally, I came up with this:
jmeter_md5_list.sort(key=lambda val: list(map(int, re.compile('(\d+(?!$))').findall(val))))
However, based on Ignacio Vazquez-Abrams's answer, I made the following changes.
def sortable_key_from_string(value):
version_tuple = tuple(map(int, re.compile('(\d+(?!$))').findall(value)))
match = re.match('^(\D+)', value)
version_name = ''
if match:
version_name = match.group(1)
return (version_tuple, version_name)
and this:
jmeter_md5_list.sort(key = lambda val: sortable_key_from_string(val))

Comparing two files in Ruby with different data types

I had an interview today and wanted input on how you would solve this issue that came up. I answered the question, but in my mind I was thinking there is a better way.
Here is the scenario. You have two files that you need to compare. In the first file you have a list in string format of NFL team abbreviations for example:
ARI
CHIC
GB
NYG
DET
WASH
PHL
PITT
STL
SF
CLEV
IND
DAL
KC
In the second file you would have the following information in a hash or json for example:
"data":
{"description": name: "CLEV","totfd":26,"totyds":396,"pyds":282,"ryds":114,"pen":4,"penyds":24,
"trnovr":0,"pt":4,"ptyds":163,"ptavg":36,"top":"37:05"}},"players":null}
How would you take the strings in the first file (the abbreviations) and see if that abbreviation was included somewhere in the data of the second file? So, for example I want to see if CLEV, ARI, WASH, so on would be anywhere in the second file. If that abbreviation is included I would want to extract information based on that abbreviation.
Here was my answer:
I would iterate over each abbreviation looking for that specific abbreviation inside the second file.
I felt my answer was poor, but I wanted to see if others had a good idea on what they would do.
thanks
Mike Riley
You should ask questions in your interview. Some questions I'd ask:
Will the hash/json include duplicate data for teams? Meaning, will CLEV have multiple records in there? If not, now you know you have unique data so there's no need to group anything ahead of time.
If it's not unique, I'd get a list of all the names that exist in the hash, so you can do a comparison between the array given and the other file.
This is in O(n) for the traversal + O(logN) for the value lookup:
hash = [{'description': 'some team', 'name': 'CLEV','totfd':26,'totyds':396,'pyds':282 },
{'description': 'some team', 'name': 'PHL','totfd':26,'totyds':396,'pyds':282 }]
hash_names = hash.map { |team| team[:name] }
Now that we have a list of names in the hash, we can find out where there is an overlap. We can add the two arrays together and figure out who shows up in there more than once. There are many ways to do that, but we should keep with our run time of O(n):
list = ["ARI","CHIC","GB","NYG","DET","WASH","PHL","PITT","STL","SF","CLEV","IND","DAL"]
teams_in_both = (list + hash_names).group_by { |team| team }.keep_if { |_, occ| occ.size > 1 }.map(&:first)
Now we have a list of:
["PHL", "CLEV"]
We know enough to say who's important to us and can fetch the remaining data accordingly.

SAS- how to do ASCENDING order when concatenating

How do you sort the values by ascending order when concatenating for SAS?
eg. In this example I am trying to acsend values for aeacnoth1_std1, aeacnoth2_std, etc.....
if cmiss( aeacnoth1_std, aeacnoth2_std)=0
then aeacolst=strip(aeacnoth1_std)||','||strip(aeacnoth2_std);
if cmiss( aeacnoth1_std, aeacnoth2_std, aeacnoth3_std)=0
then aeacolst=strip(aeacnoth1_std)||','||strip(aeacnoth2_std)||','||strip(aeacnoth3_std);
if cmiss( aeacnoth1_std, aeacnoth2_std, aeacnoth3_std, aeacnoth4_std)=0
then aeacolst=strip(aeacnoth1_std)||','||strip(aeacnoth2_std)||','||strip(aeacnoth3_std)||','||strip(aeacnoth4_std);
One possible approach:
Declare an array containing all the variables you want to concatenate
Sort the array into the desired order
Concatenate the array
The hard part is step 2, as SAS 9.1 or earlier doesn't provide any direct way of doing this. You might find this paper useful, or just Google for 'sas sort array' and see what comes up:
http://www2.sas.com/proceedings/sugi26/p096-26.pdf
EDIT: if you have SAS 9.2 or later, you can use call sortc to sort the array:
http://support.sas.com/documentation/cdl/en/lrdict/64316/HTML/default/viewer.htm#a003106052.htm

Resources