Python List of tuples in Scala - list

I am using Jython execute the python code part (a python module with utility functions from existing codebase) that returns a list of tuples, but what I get in scala is a simple flattened list. Any suggestions on the cause would help.
Since I am a beginner with with Scala and Jython, this probably might not be the best approach to solve the problem. I call the python function as shown below:
val viaJython = true
val interp = new PythonInterpreter()
val pyCode =
interp.compile(
"""import myModule as df
| aList = df.find_date(foundVal)"""
)
interp.set("foundVal", foundVal)
interp.exec(pyCode)
println(interp.get("aList"))

A simple solution may be: If you get a flattened List and you know the tuple size n then it can be unflattened into a List of Lists with List.grouped(n).toList. Then the sublists can be converted to tuples with map as shown below or using methods given at Convert a Scala list to a tuple? and Is there way to create tuple from list(without codegeneration)?. If you do not know the tuple length then you can find out by examining the bytecode generated by javap -c on the class file.
Another method is to use the implicit conversions from Java collections, iterators, iterables and enumerators which Scala provides. To apply them add "import scala.collection.JavaConversions._" before executing Jython and set resulting Jython List to Scala mutable.Buffer with explicit type declaration. For example, if the Jython List elements are 3-tuples of Int (Tuple3[Int,Int,Int] in Scala) then the converted Scala collection could be defined as:
val pyBuffer: scala.collection.mutable.Buffer[Tuple3[Int,Int,Int]] = ResultingJavaListFromJython
The reason for using scala.collection.mutable.Buffer is that is the collection supported by scala.collection.JavaConversions for Java List conversion. After the conversion to mutable.Buffer is done, it can be converted to any of a number of other types of collections with its "to" functions including toList to convert it to a Scala List, e.g.:
val pyList = pyBuffer.toList
For reference see http://www.scala-lang.org/api/2.11.7/#scala.collection.JavaConversions$ or the equivilant API page for whatever version of Scala you are using.
Another issue is that Java does not have tuples so Jython implements PyTuple with java.util.List and Scala does not provide conversion to Tuple. For that reason another thing to try, assuming that each PyTuple has Int elements, is:
import scala.collection.mutable.Buffer
val pyBuffer2: Buffer[Buffer[Int]] = ResultingJavaListFromJython
Then the elements of pyBuffer2 can be mapped to tuples. For example, assuming each Buffer[Int] element has 3 elements:
import scala.collection.mutable.ArrayBuffer
val pyBuffer3 = pyBuffer2.map{case ArrayBuffer(a,b,c) => (a,b,c)}
Now pyBuffer3 can be converted to Scala List with toList as shown above.
The reason for importing scala.collection.mutable.ArrayBuffer and matching on it is that it is Scala's default implementation of mutable.ArrayBuffer which is a trait.

Related

Sentry-elixir cannot encode tuples

I get it that in a pure sense, JSON doesn't account for tuples, but I don't think it's unreasonable to treat tuples as lists in terms of the JSON encoding. \Has anyone else faced and resolved this? I'd like to stay out of the business of pre-processing my error data to replace tuples with lists.
Perhaps I need to specify a different serialization approach?
EDIT: here is a practical example:
Here is some toy code.
the_data = {:ok, %{...}}
Sentry.capture_message(message, the_data)
All it does is attempt to send a message to Sentry with tuples in the data.
If you're unfamiliar with Sentry, the sentry-elixir library provides two functions (among many other, of course) that are used to explicitly send either exceptions or messages to Sentry. The functions are:
Sentry.capture_exception/2
Sentry.capture_message/2
In addition, errors are sent to Sentry when they bubble up to the "top". These can't be intercepted so I have to specify (and implement) a before_send_event "handler" in the configuration for Sentry.
This is what my configuration looks like for the environment I'm working in:
config :sentry,
dsn: "https://my_neato_sentry_key#sentry.io/33333343",
environment_name: :staging,
enable_source_code_context: true,
root_source_code_path: File.cwd!(),
tags: %{
env: "staging"
},
before_send_event: {SomeApplication.Utils.SentryLogger, :before_send},
included_environments: [:staging],
filter: SomeApplication.SentryEventFilter
My before_send function basically attempts to sanity check the data and replace all tuples with lists. I haven't implemented this entirely yet though and instead of replacing all tuples I am temporarily using Kernel.inspect/2 to convert it to a string. This isn't ideal of course, because they I can't manipulate the data in the Sentry views:
def before_send(sentry_event) do
IO.puts "------- BEFORE SEND TWO ---------------------------"
sentry_event
|> inspect(limit: :infinity)
end
This results in the following output:
{:invalid, {:ok, the_data}}
And the capture_message fails.
By default, sentry uses jason to encode its JSONs and, again by default, jason doesn't encode tuples. You can change that by implementing Jason.Encoder for Tuple:
defimpl Jason.Encoder, for: Tuple do
def encode(tuple, opts) do
Jason.Encode.list(Tuple.to_list(tuple), opts)
end
end
Be warned - this will have a global effect on how tuples are converted to JSON in your application.

Django FSM - get_available_FIELD_transitions

Using django_fsm I need to get the available transitions a list. When using the following code I do get a <generator object get_available_FIELD_transitions at 0x10b9ba660>
obj = MyModel.objects.get(pk=object_id)
transitions = obj.get_available_status_transitions()
print(transitions)
Instead I would like to get a list of transitions like ['PENDING', 'CLOSED']
The generator has everything you need, it just needs iterating. To get what you want, you can just convert it to a list:
transitions = list(obj.get_available_status_transitions())
You might want to read up on generators in Python, they're very useful.
Generators are iterable python objects. See Generators
This will print each item
transitions = list(obj.get_available_state_transitions())
print(transitions)
I found this from the test cases of django-fsm
Django-fsm TestCase

Empty list creation in kdb with no datatype

I have been learning KDB for a while now & now need your help at one point.
We can create empty list using below syntax:
mylistname:0#
Example:
q)myEmptySymbolList:0#`
q)myEmptySymbolList
`symbol$()
q)type myEmptySymbolList
11h
q)myEmptyFloatList:0#0n
q)myEmptyFloatList
`float$()
q)type myEmptyFloatList
9h
q)myEmptyDateList:0#0Nd
q)myEmptyDateList
`date$()
q)type myEmptyDateList
14h
But when we do not specify the dataType , it create list of projection function type as below.
q)myEmptyTypeList:0#
q)myEmptyTypeList
#[0]
q)type myEmptyTypeList
104h
I am bit perplexed , why it creates list of projections function type ?
If I wanted to create list of other function types how we can do that (like https://code.kx.com/wiki/Reference/Datatypes#Function_Types ) & where in development we can use list of functions ?
Thanks,
Vajindar.
In kdb, taking a zero-count of a scalar or atom value (like 0#1) is effectively a short-cut to creating an empty list.
It can be useful to use this shortcut, but for general purposes you can start with the generic list: ()
You can then cast this list using $ and either a symbol, character or short:
q)`int$()
`int$()
q)"i"$()
`int$()
q)6h$()
`int$()
These all result in an empty integer list.
In your final part above, # is a dyadic function - you're not actually creating a list of projections here when you do 0#, instead you're creating a single projection. There are no typed lists of functions in kdb:
q)type ({x+1};{x+2})
0h
They always appear as a mixed list (type 0), so you're just seeing the (positive) type of the projection you've created in this case (104).
There is an updated list of types here:
https://code.kx.com/q/ref/datatypes/
And information on casting here:
https://code.kx.com/q/ref/casting/#cast

Elixir: Find middle item in list

I'm trying to learn Elixir. In most other languages i've battled with, this would be an easy task.
However, i can't seem to figure out how to access a list item by index in Elixir, which i need for finding the median item in my list. Any clarification would be greatly appreciated!
You will want to look into Enum.at/3.
a = [1,2,3,4,5]
middle_index = a |> length() |> div(2)
Enum.at(a, middle_index)
Note: This is expensive as it needs to traverse the entire list to find the length of the list, and then traverse halfway through the list to find what the actual element is. Generally speaking, if you need random access to an item in a list, you should be looking for a different data structure.
This is how I would do it:
Enum.at(x, div(length(x), 2))
Enum.at/3 retrieves the value at a particular index of an enumerable. div/2 is the equivalent of the Python 2.x / integer division.

concatenating a string onto all elements of [string] haskell

I'm new to haskell and can't seem to figure this out. I've been using the scalpel web scraping tool and want to concatenate a bunch of URL extensions with a URL.
For example, lets say we have scraped some URL extensions into a list of strings
result =["/contact","/content"]
and we have let
websiteURL = "www.website.com"
how do I arrive at the list ?
["www.website.com/contact", "www.website.com/content"]
map ("aaa"++) ["bbb", "ccc"]
==> [ "aaabbb", "aaaccc" ]
You want to traverse your list of extensions and apply a function to each, so some kind of map is required.
The function you want to apply is to append the websiteURL string, so the answer is:
map (mappend websiteURL) result
If you didn't know the mappend function, you could find it by searching hoogle for Monoid a => a -> a -> a.
(I'll let other people generalize to more abstract types if they want...)