Hi there, folks. I am wanting to do a sort-by
(or some sort of a sort) on a map with two keys in two directions. For example, I want to sort last name reverse-alphabetically, and then ties broken by first name by regular alphabetical order. So, given a list of data:
(def heroes '({:last-name "Stark", :first-name "Howard"}
{:last-name "Wilson", :first-name "Sam"}
{:last-name "Banner", :first-name "Bruce"})
{:last-name "Stark", :first-name "Tony"})
I want it to sort like this:
({:last-name "Wilson", :first-name "Sam"}
{:last-name "Stark", :first-name "Howard"}
{:last-name "Stark", :first-name "Tony"}
{:last-name "Banner", :first-name "Bruce"})
My brain is really swimming how to make this work. Can you help? ๐ฑthere's probably a more succinct version, but this seems to work:
(sort-by (juxt :last-name :first-name)
(fn [[x0 x1] [y0 y1]]
(let [c (- (compare x0 y0))]
(if-not (zero? c)
c
(compare x1 y1))))
heroes)
Ahhh, I was thinking about needing a compare
function in there, but I could not figure out how to make it work. Thanks, @smith.adriane!
you don't need that custom compare i don't think. vectors sort positionally like that by default:
(sort-by (juxt :last-name :first-name)
compare
[{:last-name "Stark", :first-name "Howard"}
{:last-name "Wilson", :first-name "Sam"}
{:last-name "Banner", :first-name "Bruce"}
{:last-name "Stark", :first-name "Tony"}])
I think the custom comparator is required to sort last name descending and first name ascending
using compare
rather than the custom comparator gives a different order than the example output
Oh sorry I missed descending. Youโre totally right
This article might be way more than you want to know, but a good understanding of its contents might be what you are looking for: https://clojure.org/guides/comparators
The only thing I could find that'd make @smith.adriane's solution more succinct is that you can reverse the order of the arguments of the first compare instead of negating the result:
(sort-by (juxt :last-name :first-name)
(fn [[x0 x1] [y0 y1]]
(let [c (compare y0 x0)]
(if-not (zero? c)
c
(compare x1 y1))))
heroes)
saves 4 whole characters! ๐I am trying to make a Datomic account but it asks for an Organization when I am not part of one. Can I put โNoneโ or something?
Also: are there still free editions of Datomic available for me to test out? There were some blogposts from ~8 years ago but the only plans seem to be Solo and Production
I haven't checked carefully, but there are cases where using negation can lead to very subtle and occasional bugs in comparison functions, with some examples at the article I linked. That is a much more important reason to be wary of negation there than how many characters it is.
Thank you!
Also, what would I put for my organization?
@michaellan202 "Free" doesn't exist any more -- that link hasn't had releases since 2019. You want the Cognitect Dev Tools to do free local dev with Datomic now. https://www.cognitect.com/dev-tools/ to download, https://docs.datomic.com/cloud/dev-local.html for more details.
Datomic is all cloud now.
Thank you for letting me know!
wait, but the release date for the most recent version says 2021-03-09 thoughโฆ
The link @hiredman gave only has updates to 2019. The dev-local stuff has been updated recently, as you saw.
I used the Datomic Pro Free Edition thing. Is that outdated as well?
Link?
If you are just learning Datomic, use the dev-local setup. If you are planning to run Datomic in production, you need a license even for the starter edition.
You can always ask in #datomic if you're not sure how to proceed.
how can i turn a string into a map in clojurescript? i thought it was cljs.reader/read-string
but i'm not able to do normal map operations on the resultant piece even though it seems like one ought be able
What is the value of (type x)
, where x
is the return value from (cljs.reader/read-string some-string)
you're a genius! let's see...
clojurescript say function PersistentArrayMap(meta, cnt, arr, __hash)
seems correct? o.O
thanks ๐ resolved
Hi. Please help me publish my test app on clojar.
I created a test app with this cmd lein new app my-app
I modified the project.clj
file with this ..
1 โ (defproject my-app "0.1.0-SNAPSHOT"
2 โ :description "testing deploy"
3 โ :url "<https://clojars.org/groups/org.clojars.kyp0717>"
4 โ :license {:name "EPL-2.0 OR GPL-2.0-or-later WITH Classpath-exception-2.0"
5 โ :url "<https://www.eclipse.org/legal/epl-2.0/>"}
6 โ :dependencies [[org.clojure/clojure "1.10.1"]]
7 โ :main my-app.core
8 โ :target-path "target/%s"
9 โ :profiles {:uberjar {:aot :all
10 โ :jvm-opts ["-Dclojure.compiler.direct-linking=true"]}})
Finally, I published with this cmd lein deploy clojars
My version of lein is Leiningen 2.9.5 on Java 11.0.10 OpenJDK 64-Bit Server VM
What am I doing wrong?
Here is the error message ...
No credentials found for clojars
See `lein help deploying` for how to configure credentials to avoid prompts.
Username: kyp0717
Password:
Compiling my-app.core
Created /home/phage/tmp/my-app/target/my-app-0.1.0-SNAPSHOT.jar
Wrote /home/phage/tmp/my-app/pom.xml
Could not find metadata my-app:my-app:0.1.0-SNAPSHOT/maven-metadata.xml in clojars (<https://repo.clojars.org/>)
Sending my-app/my-app/0.1.0-SNAPSHOT/my-app-0.1.0-20210404.155005-1.jar (14k)
to <https://repo.clojars.org/>
Could not transfer artifact my-app:my-app:jar:0.1.0-20210404.155005-1 from/to clojars (<https://repo.clojars.org/>): Failed to transfer file <https://repo.clojars.org/my-app/my-app/0.1.0-SNAPSHOT/my-app-0.1.0-20210404.155005-1.jar> with status code 401
Sending my-app/my-app/0.1.0-SNAPSHOT/my-app-0.1.0-20210404.155005-1.pom (2k)
to <https://repo.clojars.org/>
Could not transfer artifact my-app:my-app:pom:0.1.0-20210404.155005-1 from/to clojars (<https://repo.clojars.org/>): Failed to transfer file <https://repo.clojars.org/my-app/my-app/0.1.0-SNAPSHOT/my-app-0.1.0-20210404.155005-1.pom> with status code 401
Failed to deploy artifacts: Could not transfer artifact my-app:my-app:jar:0.1.0-20210404.155005-1 from/to clojars (<https://repo.clojars.org/>): Failed to transfer file <https://repo.clojars.org/my-app/my-app/0.1.0-SNAPSHOT/my-app-0.1.0-20210404.155005-1.jar> with status code 401
@kyp0717 what's the error you get?
xD thank you
Hmmm a 401
Unauthorized client error status
The HTTP 401 Unauthorized client error status response code indicates that the request has not been applied because it lacks valid authentication credentials for the target resource.
@sova Do I need to set up a token? I assume NOT since it is just a simple test deployment to my group which is https://clojars.org/groups/org.clojars.kyp0717
This is a great question. I don't know anything about deploying to clojars ๐ but someone probably does.
Yes I think you need a token.
@sova I have tested my connection to clojar by successfully logging in to the group webpage. I am using the same id and password on the command line.
@kyp0717 hopefully the deploy token works.
To deploy to Clojars, you will need to authenticate yourself. Deployment authentication is done via your username and a Deploy Token.
I am trying to avoid using token as it said that token it is NOT needed for this type of deployment. Is this true?
https://github.com/clojars/clojars-web/wiki/Tutorial at the bottom note the group needs to be added to the defproject
so yours should probably be (defproject org.clojars.kyp0717/my-app "0.1.0-SNAPSHOT" ...
hi, is there a more idiomatic way to simply replace a value in map, disregarding the old val than this one:
(update map :something (fn [_ a] (function a)) 10)
@vanchuck I modifed the project.clj file to ....
(defproject org.clojars.kyp0717/my-app "0.1.0-SNAPSHOT"
:description "testsing deploy"
:url "<https://clojars.org/groups/org.clojars.kyp0717>"
:license {:name "EPL-2.0 OR GPL-2.0-or-later WITH Classpath-exception-2.0"
:url "<https://www.eclipse.org/legal/epl-2.0/>"}
:dependencies [[org.clojure/clojure "1.10.1"]]
:main my-app.core
:target-path "target/%s"
:profiles {:uberjar {:aot :all
:jvm-opts ["-Dclojure.compiler.direct-linking=true"]}})
But I got this error ...
No credentials found for clojars
See `lein help deploying` for how to configure credentials to avoid prompts.
Username: kyp0717
Password:
Compiling my-app.core
Created /home/phage/tmp/my-app/target/my-app-0.1.0-SNAPSHOT.jar
Wrote /home/phage/tmp/my-app/pom.xml
Could not find metadata org.clojars.kyp0717:my-app:0.1.0-SNAPSHOT/maven-metadata.xml in clojars (<https://repo.clojars.org/>)
Sending org/clojars/kyp0717/my-app/0.1.0-SNAPSHOT/my-app-0.1.0-20210404.161209-1.jar (14k)
to <https://repo.clojars.org/>
Could not transfer artifact org.clojars.kyp0717:my-app:jar:0.1.0-20210404.161209-1 from/to clojars (<https://repo.clojars.org/>): Failed to transfer file <https://repo.clojars.org/org/clojars/kyp0717/my-app/0.1.0-SNAPSHOT/my-app-0.1.0-20210404.161209-1.jar> with status code 401
Sending org/clojars/kyp0717/my-app/0.1.0-SNAPSHOT/my-app-0.1.0-20210404.161209-1.pom (2k)
to <https://repo.clojars.org/>
Could not transfer artifact org.clojars.kyp0717:my-app:pom:0.1.0-20210404.161209-1 from/to clojars (<https://repo.clojars.org/>): Failed to transfer file <https://repo.clojars.org/org/clojars/kyp0717/my-app/0.1.0-SNAPSHOT/my-app-0.1.0-20210404.161209-1.pom> with status code 401
Failed to deploy artifacts: Could not transfer artifact org.clojars.kyp0717:my-app:jar:0.1.0-20210404.161209-1 from/to clojars (<https://repo.clojars.org/>): Failed to transfer file <https://repo.clojars.org/org/clojars/kyp0717/my-app/0.1.0-SNAPSHOT/my-app-0.1.0-20210404.161209-1.jar> with status code 401
I have not create a github repo. Will I need to create a github repo to deploy to clojar?
are you looking for assoc
?
you are right! I am, I didnโt realise I can use it on existing keys, I thought it was just about adding new ones
assoc, dissoc, assoc-in, reset! are all some helpful friends
Hmmm, and you made a group on clojars?
I think @sova is right, you need to use deploy tokens:
https://github.com/clojars/clojars-web/wiki/Pushing > leiningen 2.0.0 > lein deploy clojars > This will prompt you for your username and password*. For your password, you will need to create one or more https://github.com/clojars/clojars-web/wiki/Deploy-Tokens.* It is also possible to have them read from an https://github.com/technomancy/leiningen/blob/master/doc/DEPLOY.md#authentication.
I will create a token. Will I need to create a github repo too?
don't think so, docs don't mention github
@sova Yes. I believe this is my group on clojars ...https://clojars.org/groups/org.clojars.kyp0717
Ok thanks
glad you found out the issue. I was AFK for a while there.
Hiya, is there a way of simplifying these nested if statements (my code):
(defn main [severity]
(println (str "We're")
(if (= severity :mild)
"mildly inconvenienced."
(if (= severity :severe)
"doomed."))))
into something more concise like this?:
(defn math [opr x y]
(({"add" +, "times" *} opr) x y))
Here's where i found the more concise function https://stackoverflow.com/questions/21681374/clojure-with-multiple-if-statements/21684980#21684980cond
or case
will both let you remove that nesting.
Or you can just use a hash map, keyed by :mild
and :severe
with strings as the values.
(defn main [severity]
(println "We're" (severity {:mild "mildly inconvenienced." :severe "doomed."})))
user=> (defn main [severity]
(println "We're" (severity {:mild "mildly inconvenienced." :severe "doomed."})))
#'user/main
user=> (main :severe)
We're doomed.
nil
user=> (main :mild)
We're mildly inconvenienced.
nil
user=> (main :what)
We're nil
nil
user=>
Note the last case.Here's a variant that provides a "not found" value:
user=> (defn main [severity]
(println "We're" (severity {:mild "mildly inconvenienced." :severe "doomed."} "OK.")))
#'user/main
user=> (main :what)
We're OK.
nil
user=>
That is exactly what I was looking for, thank you.
(kw hash-map not-found)
is like (get hash-map kw not-found)
Also (hash-map kw not-found)
also means (get hash-map kw not-found)
Hi everyone, I have 3 lists of numbers with values 0
or 30/40/50
I want to create a new list where it gives me true (or 1) when the 3 lists are all not= 0
What might be the best way to do this?
Wanted to do map over and
but could only do
(and
(map #(not= 0 %) [0 0 0 0 40 0])
(map #(not= 0 %) [0 0 0 0 0 30])
(map #(not= 0 %) [0 0 0 50 0 0]))
Where I don't quite understand why and
here just gives me the value of the last list
Per the docstring
Evaluates exprs one at a time, from left to right. If a form
returns logical false (nil or false), and returns that value and
doesn't evaluate any of the other expressions, otherwise it returns
the value of the last expr. (and) returns true.
@zackteo Itโs not a strictly Boolean operation โ because false
/`nil` are โfalseyโ and everything else is โtruthyโ in Clojure.
Right right :thinking_face: how do I map over and
then? Is that possible? I realise there's another way to solve my problem already but don't quite understand why (map and ...)
does not work
not sure what you mean by map
over and
. Can you provide an example output? My guess is that you want some
somewhere
@smith.adriane I would like to be able to do this I believe
(map and
(map #(not= 0 %) [0 0 0 0 40 0])
(map #(not= 0 %) [0 0 0 0 0 30])
(map #(not= 0 %) [0 0 0 50 0 0]))
I think you're looking for every?
, @zackteo
like this?
(map (fn [& xs]
(every? identity xs))
(map #(not= 0 %) [1 0 0 0 40 0])
(map #(not= 0 %) [1 0 0 0 0 30])
(map #(not= 0 %) [1 0 0 50 0 0]))
;; (true false false false false false)
I changed the example slightly so that there would be at least one true result
Wow okay okay. Never saw the need to use every?
until now ๐ฎ
Thanks!
I think this gives the same result but I'm not 100% sure
(map (fn [& xs]
(not-any? #(= 0 %) xs))
[1 0 0 0 40 0]
[1 0 0 0 0 30]
[1 0 0 50 0 0])
user=> (map #(not-any? zero? %&)
[1 0 0 0 40 0]
[1 0 0 0 0 30]
[1 0 0 50 0 0])
(true false false false false false)
Using zero?
is more idiomatic than #(= 0 %)
and then you can use #
for the anonymous mapped function (`%&` is not used very often but itโs a good fit here)(map and ...)
does not work because and
is a macro
Also, could I ask with two lists [43 51 37 41]
and [true false true false]
How do I get something like [43 0 37 0]
where it returns me the value if it is true and 0 if false?
My first instinct if any is using for
but not too sure actually
You can map over both colls simultaneously and have a condition to either return the num or 0 if false
How do I choose which coll to access in a map ? ๐ฎ
(mapv
(fn [x1 x2]
(if (true? x2) x1 0))
[43 51 37 41]
[true false true false])
=> [43 0 37 0]x1 is each item in the first coll, x2 is each item in the second coll
(fn [โฆ]) should take a number of arguments equal to the number of collections youโre going over at the same time
A hacky way to make it work is:
(let [v1 [true false]
v2 [true true]
v3 [false false]]
(mapv #(eval `(and ~@%)) [v1 v2 v3]))
Ohhh okay okay! I was thinking about that. Cause the functions I have been using in map seems to like work uniformly across the colls like +
But (eval โฆ) is generally not recommended if another solution is possible (almost always is)
Thanks everyone for your help!! ๐
Learnt quite a fair bit from all the responses!