Clojure fill map using into - parsing

I need to fill map {:v '[], :f '[]), where v-array contains data from line that starts with v. How can I do this?
Example of file:
# comment
v 1.234 3.234 4.2345234
v 2.234 4.235235 6.2345
f 1 1 1
Expected result:
{:v [(1.234 3.234 4.2345234) (2.234 4.235235 6.2345)]
:f [(1 1 1)] }
My try:
(defn- file-lines
[filename]
(line-seq (io/reader filename)))
(defn- lines-with-data
[filename]
(->>
(file-lines filename)
(filter not-empty)
(filter #(not (str/starts-with? % "#")))))
(defn- create-model
[lines]
(doseq [data lines]
(into {:v '[] :f '[]}
(->>
(let [[type & remaining] data]
(case type
"v" [:v remaining]
"f" [:f remaining]))))))
(defn parse
[filename]
(->>
(lines-with-data filename)
(map #(str/split % #"\s+"))
(create-model)))
Exception:
user=> (p/parse "test.obj")
IllegalArgumentException Don't know how to create ISeq from: clojure.lang.Keyword clojure.lang.RT.seqFrom (RT.java:542)
(parse should be return result map)

I can repeat your error message like this:
(into {:v '[] :f '[]} [:v [:a :b]])
I can do what I think the program requires like this:
(assoc {:v '[] :f '[]} :v [:a :b])
;; => {:v [:a :b], :f []}
Here I just used [:a :b] instead of remaining. In your case remaining is a sequence of numbers, but it doesn't really matter.
As for the error message it is quite a bad one, that should be gone in coming versions of Clojure. Usually it is because you are presenting map with a keyword rather than something that seq can be called on. Here the message is coming from somewhere a bit deeper than I can comprehend.
Another construction that would work, and is I think what you wanted, is:
(into {:v '[] :f '[]} [[:v [:a :b]]])
into a map requires a sequence of map-entry. You forgot to wrap the single map-entry you were trying to place into the map. Result from my REPL:
{:v [:a :b], :f []}

Related

Neo4j: Cypher query how to match result with value only contains in array

I have a neo4j with label (A)-[:REL]->(B), I want to select node A that have :REL with B where B.id only in input array(B.id dont have diff value with input)
Example:
A1 :REL B1: {id:[1,2,3]}
A2 :REL B2: {id:[1,3]}
A3 :REL B3: {id:[3]}
with input array [1,3]
return A2 & A3, because A1 have :REL with B id=2 not in input array
I have tried this but not correct, still return A1
where apoc.coll.contains([1,3],b.id)
Thanks.
I found it:
match(A)-[:REL]->(B)
with A,collect(B.id) as ids
WHERE NOT ANY (x IN ids WHERE NOT x IN {inputArray})
Thanks all

Parsing search results from website, compojure/clojure

For some time I'm working on a simple clojure project for movies, so I'm trying to parse search results from a particular web site, in my case imdb.com. Not sure If I'm on the right track for this so I'm hoping someone would help me out.
Homepage will look simple enough, with text-field where you would enter movie name and submit button named "Search". I'll try to be as much deatailed as possible:
1.This is the main page:
(defn view-input []
(view-layout
[:h2 "Find your Movie"]
[:body {:style "font: 14pt/16pt helvetica; background-color: #F2FB78; padding-top:100px; text-align: center" }
(form-to [:post "/"]
[:br]
[:br]
(text-field {:placeholder "Enter movie name" } :a) [:br]
(submit-button "Search")
)]
))
2.These are the functions that I've been using:
(defn create-flick-url [a]
(str "http://www.imdb.com/search/title?title=" a "&title_type=feature"
))
(defn flick-vec [categories a]
(vec (let [flick-url (create-flick-url a)
flick-names (print-flick-name-content flick-url)]
(mapper-gen4 flick-names
(get-image-content flick-url)
))) )
(defn view-output2 [categories a]
(view-layout
[:h2 "Search results"]
[:form {:method "post" :action "/"}
(interleave
(for [flick (flick-vec categories a)]
(label :title (:name flick)))
(for [flick-name (flick-vec categories a)]
[:br])
(for [flick-image (flick-vec categories a)]
[:img {:src (:image flick-image)}])
(for [flick (flick-vec categories a)]
[:br]))
]))
3.And this is the GET/POST part in the same class, where I'm using the view-output and view-output2 functions :
(defroutes main-routes
(GET "/" []
(view-input))
(POST "/" [categories a]
(view-output2 categories a))
4.Also, these are the functions that previous ones are using:
(defn print-flick-name-content
[url]
(vec (flatten (map :content (h3+table url)))))
(defn get-image-content
[url]
(vec (flatten (map #(re-find #"http.*jpg" %)
(map :style (map :attrs (h3+table2 url)))))))
(defn get-page
"Gets the html page from passed url"
[url]
(html/html-resource (java.net.URL. url)))
(defn h3+table
"Return seq of <h3> and table tags, where content of the <h3> tag meet defined condition"
[url]
(html/select (get-page url)
[:td (html/attr= :class "title") :h3 :a]))
(defn h3+table2
"Return seq of <h3> and table tags, where content of the <h3> tag meet defined condition"
[url]
(html/select (get-page url)
[:td (html/attr= :class "image")]))
5.And here's the last one, function defined in another class which deals with map:
(defn mapper-gen4
[names images] (sort-by :name (map #(hash-map
:name %1 :image %2) names images)))
I know it's a bit much, but this way someone will see where the problem is, so far the Search result page shows no results, nor errors, only blank page with h2 Search Results title. Thanks in advance!
I would start at the form handling route:
(POST "/" [categories a]
(view-output2 categories a))
inserting a humble print statement:
(POST "/" [categories a]
(do
(println "CAT" categories "A" a)
(view-output2 categories a)))
Make sure your handler includes wrap-reload so you can refresh the page and check the console. You might see that categories and a are nil, in which case you might next try something like this:
(POST "/" req
(do
(println "REQ" req)
(view-output2 *hard-coded-categories* *hard-coded-a*)))
Replace hard-coded-categories and hard-coded-a with the data structure you are expecting to see. This will test:
You will see in the request where the parameters are.
You will see whether your rendering code does what you expect with the right data.
If indeed the problem is that categories and a are nil, it might just be that you forgot a middleware handler (see why this matters).
If they contain the data you expect in the structure you expect, then it is time to drill down into your other functions. For this I recommend using a REPL session and calling your top level function with the hard-coded values you are expecting from the form, however if you are using wrap-reload you could also just resubmit the form. For example you could add printouts of the inputs and outputs of your mapper-gen4 function and get-page function.
Finally after playing with some values and results, copy these from your REPL into a test file so that you have some permanent assertions about how your code behaves.
If all else fails, posting a link to your github project will get you better help - or if it is private, create a minimal example project so that people can help you more precisely.

How do I take a substring of a string with multiple quotes? Rails/Ruby

Given a string such as (Shift opened: \"he clams \"sick\" but not sure\") how would I extract just the part between the first set of quotes? I've tried combinations of split, slice and squeeze but always run into a case where it doesn't work. Thanks.
EDIT: The user inputs text, which can be in any form, so yes, someone could have an odd number of quotes. The text before the input is generated for record purposes. Some examples:
n = (Shift opened: \"he clams \"sick\" but not sure\")
n.split('"')[1] > "he claims "
If I could find the size of the array created by split I could do split('"')[1..size-1] but I'm not sure how to find that.
n = (Shift opened: \"\"sick\"\")
n.squeeze('"').split('"')[1] >> "sick"
That works fine.
This is more for error checking and making sure if people use quotes on input, it doesn't mess things up. And no I cannot edit how the string is generated. Hope I'm clear enough!
You can leverage the fact that regex is greedy by default, and use /"(.*)", which will capture all text between the first and last quotes:
n = 'Shift opened: "he clams "sick" but not sure" some more text'
n[/"(.*)"/, 1]
# => "he clams "sick" but not sure"
n = "Shift opened: \"\"sick\"\""
n[/"(.*)"/, 1]
# => ""sick""
I'm not sure if you want to extract the text on quotes recursively and get something like this:
=> "he clams "sick" but not sure"
=> "sick"
or "lorem ipsum "xxxxx yyyy "alpha beta" zzzz wwww" dol"
=> "lorem ipsum "xxxxx yyyy "alpha beta" zzzz wwww" dol"
=> "xxxxx yyyy "alpha beta" zzzz wwww"
=> "alpha beta"
perhaps you will need a simple CFG:
S -> aS | a
a = /\".*\"/
or iterate the string stacking substrings on each quote

How do I print an array in Rails?

I am new to Rails and I am using Ruby version 1.9.3 and Rails version 3.0.0.
I want to print an array in Rails. How do I do that?
For example, we have to use print_r to print an array in PHP:
<?php
$a = array ('a' => 'apple', 'b' => 'banana', 'c' => array ('x', 'y', 'z'));
print_r ($a);
?>
Output:
<pre>
Array
(
[a] => apple
[b] => banana
[c] => Array
(
[0] => x
[1] => y
[2] => z
)
)
</pre>
How do I print an array in Rails?
You can use inspect like:
#a = ['a', 'b']
p #a #['a', 'b']
Or:
p #a.inspect #"[\"a\", \"b\"]"
You need to use awesome_print gem.
require 'awesome_print'
hash = {:a=>1,:b=>2,:c => [1,2,3]}
ap hash
output:
{
:a => 1,
:b => 2,
:c => [
[0] 1,
[1] 2,
[2] 3
]
}
It depends on what you want to use the array for.
To blindly output an array in a view, which has to be in a view, you should use debug and inspect like this:
<%= #array.inspect() %>
<%= debug #array %>
However, if you want to iterate through an array, or do things like explode(), you'll be better suited using the Ruby array functions.
You've got a couple of options here. I'm assuming you're doing this in an ERB template.
This will convert the array to YAML and print it out surrounded in <pre> tags
<%= debug [1,2,3,4] %>
And this will print it out formatted in a readable Ruby syntax:
<pre><%= [1,2,3,4].inspect %></pre>
Check out "Debugging Rails Applications" for more info.

Rails print whitespace from controller

I'd like to debug a variable #num in my Rails controller, so I'm evaluating
<%= #num %>
in my Rails view. However, I cannot distinguish between #num being '', ' ', and ' ' (and other different types of whitespace) when it's printed in the HTML. Is there any way to print it out clearly?
If you want to be really sure:
<%= #num.inspect %>
When #num = ' ' this should render:
" "
#inspect is great when you want to a representation of some object as a string.
If this is a complex object or large array or deep hash, I often prefer #to_yaml for inspection which lays it out in a somewhat readable format.
# controller
#foo = {:a => [:bar, :baz], :b => 123, :c => 'omg'}
# view
<pre><%= #foo.to_yaml %></pre>
# visible output
---
:b: 123
:c: omg
:a:
- :bar
- :baz
<%=debug #num %>
Will format it in haml.
<%= #num.inspect %>
Will format it as "p" does.
See Debugging Rails Applications (rails guides)

Resources