I am totally new in Scala, could you help me with the simple function -
input parameter is an integer, the function should return a list of integers with the first entry is input integer , and the rest are gotten by omitting the left most digit one by one. For example,
if input is 0, it returns List(0), input =5678 returns List(5678,678,78,8).
def leftTrunc(input:Int):List[Int]
Thanks a lot in advance
5678.toString.tails.toList.init.map(_.toInt)
//> res0: List[Int] = List(5678, 678, 78, 8)
Convert the number to a String. Then tails does exactly what you want. Except it's an iterator, so convert it to a List, and also it has an empty string at the end, so use init to return all but the last element. But they're strings, so use map to convert them all to Int again
But I'm pretty sure your instructor is expecting you to do it numerically :)
Here's a numerical version, in this case deliberately uncommented so you can work out for yourself how it works
val n = 5678
val digits = n.toString.size
List.iterate(10, digits)(10*) map { n % _}
EDIT: As requested in the comment, the other way around just uses inits instead of tails (and a reverse to get the requested ordering)
5678.toString.inits.toList.init.reverse.map(_.toInt)
//> res0: List[Int] = List(5, 56, 567, 5678)
And the numerical one is easier this way around
List.iterate(n, digits)(_/10).reverse
It's a lot of fun if you share your attempt, and we all can give our attempts too. :) I hope you've got some and here's a couple of ideas form my end...
"5678".foldRight(Seq[String](""))((c, s) => s"$c${s.head}" +: s).dropRight(1)
"5678".foldRight(Seq[String]())((c, s) => s"$c${s.headOption.getOrElse("")}" +: s)
Related
I am reading the Python Cookbook 3rd Edition and came across the topic discussed in 2.6 "Searching and Replacing Case-Insensitive Text," where the authors discuss a nested function that is like below:
def matchcase(word):
def replace(m):
text = m.group()
if text.isupper():
return word.upper()
elif text.islower():
return word.lower()
elif text[0].isupper():
return word.capitalize()
else:
return word
return replace
If I have some text like below:
text = 'UPPER PYTHON, lower python, Mixed Python'
and I print the value of 'text' before and after, the substitution happens correctly:
x = matchcase('snake')
print("Original Text:",text)
print("After regsub:", re.sub('python', matchcase('snake'), text, flags=re.IGNORECASE))
The last "print" command shows that the substitution correctly happens but I am not sure how this nested function "gets" the:
PYTHON, python, Python
as the word that needs to be substituted with:
SNAKE, snake, Snake
How does the inner function replace get its value 'm'?
When matchcase('snake') is called, word takes the value 'snake'.
Not clear on what the value of 'm' is.
Can any one help me understand this clearly, in this case?
Thanks.
When you pass a function as the second argument to re.sub, according to the documentation:
it is called for every non-overlapping occurrence of pattern. The function takes a single match object argument, and returns the replacement string.
The matchcase() function itself returns the replace() function, so when you do this:
re.sub('python', matchcase('snake'), text, flags=re.IGNORECASE)
what happens is that matchcase('snake') returns replace, and then every non-overlapping occurrence of the pattern 'python' as a match object is passed to the replace function as the m argument. If this is confusing to you, don't worry; it is just generally confusing.
Here is an interactive session with a much simpler nested function that should make things clearer:
In [1]: def foo(outer_arg):
...: def bar(inner_arg):
...: print(outer_arg + inner_arg)
...: return bar
...:
In [2]: f = foo('hello')
In [3]: f('world')
helloworld
So f = foo('hello') is assigning a function that looks like the one below to a variable f:
def bar(inner_arg):
print('hello' + inner_arg)
f can then be called like this f('world'), which is like calling bar('world'). I hope that makes things clearer.
I am attempting to learn Scala, and I'm trying to parse a JSON file. I have two lines of code:
var jVal:JValue = parse(json);
val totalCount:Int = (jVal \\ "totalCount").asInstanceOf[Int];
However, (jVal \\ "totalCount") returns a JInt instead of an int. If I print it as a string, it looks like "JInt(38)".
How on earth do I convert this to a regular int? My current code throws an exception saying that
net.liftweb.json.JsonAST$JInt cannot be cast to java.lang.Integer
I've scoured the internet, but I can't find any answers. I would really prefer not to manually parse and remove the "JInt()" part of the string just to get it as an integer.
Surely I am missing a simple way to do this?
Since JInt is a case class, a convenient way to extract the value is using an extractor expression, either in a match:
myJValue match {
case JInt(x) => /* do something with x */
case JString(s) => /* do something with s */
/* etc. */
}
or just an assignment statement, when you know what type to expect:
val JInt(totalCount) = (jVal \\ "totalCount")
This will define totalCount to be the value of "totalCount" in your JSON. Note that it will be of type BigInt. If you want to, you can convert your BigInt to an Int with the toInt method. But if your number is too big for an Int, this method will give you a different number instead of an error. So if huge numbers are at all a possibility, you'll want to check first with isValidInt.
You can also get the value using the num field or values method, but in your code that's harder to work with. To use num, you'd have to do a cast of your JValue to JInt. And if you don't cast to JInt, you won't know the type of the result of values.
I have a string function (and I am sure it is reversible, so no need to test this), could I call it in reverse to perform the opposite operation?
For example:
def sample(s):
return s[1:]+s[:1]
would put the first letter of a string on the end and return it.
'Output' would become 'utputO'.
When I want to get the opposite operation, could I use this same function?
'utputO' would return 'Output'.
Short answer: no.
Longer answer: I can think of 3, maybe 4 ways to approach what you want -- all of which depend on how are you allowed to change your functions (possibly restricting to a sub-set of Python or mini language), train them, or run them normally with the operands you are expecting to invert later.
So, method (1) - would probably not reach 100% determinism, and would require training with a lot of random examples for each function: use a machine learning approach. That is cool, because it is a hot topic, this would be almost a "machine learning hello world" to implement using one of the various frameworks existing for Python or even roll your own - just setup a neural network for string transformation, train it with a couple thousand (maybe just a few hundred) string transformations for each function you want to invert, and you should have the reverse function. I think this could be the best - at least the "least incorrect" approach - at least it will be the more generic one.
Method(2): Create a mini language for string transformation with reversible operands. Write your functions using this mini language. Introspect your functions and generate the reversed ones.
May look weird, but imagine a minimal stack language that could remove an item from a position in a string, and push it on the stack, pop an item to a position on the string, and maybe perform a couple more reversible primitives you might need (say upper/lower) -
OPSTACK = []
language = {
"push_op": (lambda s, pos: (OPSTACK.append(s[pos]), s[:pos] + s[pos + 1:])[1]),
"pop_op": (lambda s, pos: s[:pos] + OPSTACK.pop() + s[pos:]),
"push_end": (lambda s: (OPSTACK.append(s[-1]), s[:-1])[1]),
"pop_end": lambda s: s + OPSTACK.pop(),
"lower": lambda s: s.lower(),
"upper": lambda s: s.upper(),
# ...
}
# (or pip install extradict and use extradict.BijectiveDict to avoid having to write double entries)
reverse_mapping = {
"push_op": "pop_op",
"pop_op": "push_op",
"push_end": "pop_end",
"pop_end": "push_end",
"lower": "upper",
"upper": "lower"
}
def engine(text, function):
tokens = function.split()
while tokens:
operator = tokens.pop(0)
if operator.endswith("_op"):
operand = int(tokens.pop(0))
text = language[operator](text, operand)
else:
text = language[operator](text)
return text
def inverter(function):
inverted = []
tokens = function.split()
while tokens:
operator = tokens.pop(0)
inverted.insert(0, reverse_mapping[operator])
if operator.endswith("_op"):
operand = tokens.pop(0)
inverted.insert(1, operand)
return " ".join(inverted)
Example:
In [36]: sample = "push_op 0 pop_end"
In [37]: engine("Output", sample)
Out[37]: 'utputO'
In [38]: elpmas = inverter(sample)
In [39]: elpmas
Out[39]: 'push_end pop_op 0'
In [40]: engine("utputO", elpmas)
Out[40]: 'Output'
Method 3: If possible, it is easy to cache the input and output of each call, and just use that to operate in reverse - it could be done as a decorator in Python
from functools import wraps
def reverse_cache(func):
reverse_cache = {}
wraps(func)
def wrapper(input_text):
result = func(input_text)
reverse_cache[result] = input_text
return result
wrapper.reverse_cache = reverse_cache
return wrapper
Example:
In [3]: #reverse_cache
... def sample(s):
... return s[1:]+s[:1]
In [4]:
In [5]: sample("Output")
Out[5]: 'utputO'
In [6]: sample.reverse_cache["utputO"]
Out[6]: 'Output'
Method 4: If the string operations are limited to shuffling the string contents in a deterministic way, like in your example, (and maybe offsetting the character code values by a constant - but no other operations at all), it is possible to write a learner function without the use of neural-network programming: it would construct a string with one character of each (possibly with code-points in ascending order), pass it through the function, and note down the numeric order of the string that was output -
so, in your example, the reconstructed output order would be (1,2,3,4,5,0) - given that sequence, one just have to reorder the input for the inverted function according to those indexes - which is trivial in Python:
def order_map(func, length):
sample_text = "".join(chr(i) for i in range(32, 32 + length))
result = func(sample_text)
return [ord(char) - 32 for char in result]
def invert(func, text):
map_ = order_map(func, len(text))
reordered = sorted(zip(map_, text))
return "".join(item[1] for item in reordered)
Example:
In [47]: def sample(s):
....: return s[1:] + s[0]
....:
In [48]: sample("Output")
Out[48]: 'utputO'
In [49]: invert(sample, "uputO")
Out[49]: 'Ouput'
In [50]:
We know both of this works for sorted():
sorted(['second', 'first', 'third'])
sorted([('first','second'), ('second', 'first'), ('first', 'third')])
By sorting the second one, the tuples are compared lexicographically; the first items are compared; if they are the same then the second items are compared, and so on.
But how to apply a key function on all the individual strings (or anything else there) for sorted which works for both containers and works recursively in the second case? Let's say func converts 'first' to 3, 'second' to 1 and 'third' to 2. I want this result:
['second', 'third', 'first']
[('second', 'first'), ('first','second'), ('first', 'third')]
I made this function to use as key but I dont like typechecking in it since it applies func only on strings which is not a general solution:
def recursively_apply_func_on_strings(target, func,
fargs=(), fkwargs={}):
if isinstance(target, str):
return func(target, *fargs, **fkwargs)
result, f = [], recursively_apply_func_on_strings
for elem in target:
result.append(f(elem, func, fargs, fkwargs))
return tuple(result)
sorted(sequence, key=lambda x: recursively_apply_string_func(x, func))
Is there a cleaner way to do this?
Well, despite my comment saying otherwise, I think there are a few possible ways to improve things.
One idea is to make your function a key-function factory. This way you won't need a lambda to apply it with extra arguments in your sorted call.
Another idea is to apply func to all non-iterable values (plus strings), using the abstract Iterable type from the collections module to test against.
Here's some code:
from collections import Iterable
def recursive_key(func, fargs=(), fkwargs={}):
def key_func(target):
if isinstance(target, str) or not isinstance(target, Iterable):
return func(target, *fargs, **fkwargs)
return tuple(key_func(item) for item in target)
return key_func
You'd call it like this (sorting by hexidecimal integer value, rather than string value):
sorted([('a', 'F'), ('A', 'd')], key=recursive_key(int, (16,)))
Note that we're calling recursive_key and it's return value (a.k.a. key_func) is what is being passed as the key parameter to sorted.
I get the following as a result from using the scala json parse.
import scala.util.parsing.json.JSON._
val j: String = """["this",["a","b",["c","d"]]]"""
val parse_test=parseFull(j)
now from this I get a result of Option[Any]
I can use get to obtain the results (in this case I am not concerned about invalid json format, so this should be safe, right?)
parse_test.get
res26: Any = List(this, List(a, b, List(c, d)))
Now, how should I go about going from this Any to the List that I had expected? I assume I should use pattern matching, but I can't figure it out. Any help would be much appreciated
Here is my solution:
scala> val Some(xs # List(_*)) = parse_test
xs: List[Any] = List(this, List(a, b, List(c, d)))
What you could do is a fold with a pattern match and a cast:
test_result.fold[List[String]](Nil){
case _ :: list :: _ => list.asInstanceOf[List[String]]
case _ => Nil
}
Assuming you're trying to throw out of the first element and that the 2nd element is the list you wanted.
Edit:
Be aware that if the 2nd element isn't a list this cast would cause an exception. It's really horrible dealing with a List[Any] and trying to decode what's in there...