I have an interesting situation, we have a settings database that store enum values as an int, the back end knows how to handle this but on our mobile app I'm struggle to figure how how to reproduce this.
currently I have the following:
enum class ProfileDisplayFlags(val number:Int)
{
Address(0x01),
PhoneNumber(0x02),
Email(0x04),
TwitterHandler(0x08),
GithubUsername(0x10),
Birthday(0x20)
}
for example, if I get the setting value from the database of 3, it should return on the app that I want to display Address & PhoneNumber.
I'm lost on how I can do this, I found a solution on finding a single value but I need to be able to get multiple back.
Each flag value is a different unique bit set to one, so you can filter by which ones are not masked (bitwise AND) to zero by the given flags.
companion object {
fun matchedValues(flags: Int): List<ProfileDisplayFlags> =
values().filter { it.number and flags != 0 }
}
To convert back, you can use bitwise OR on all of them.
fun Iterable<ProfileDisplayFlags>.toFlags(): Int =
fold(0) { acc, value -> acc or value.number }
Related
So the question is giving a BIG string, break it up, find the palindromes and then find the shortest length within those sets of palindromes. Here's the code
Main Function
fun main(){
val bigArray = "Simple, given a string of words, return the length of acdca the " +
"shortest valav words String will never be empty and you do not need dad to account for different data types."
println(leastP(bigArray))
}
The Custom Function
fun leastP(s: String): Int {
val sSplit = listOf(s.split(""))
val newArray = listOf<String>()
for (i in sSplit){
for (j in i.indices){
if (isPalindrome3(i[j])) newArray.plus(j)
}
}
return newArray.minOf { it.length }
}
private fun isPalindrome3(s: String): Boolean {
var i = 0
var j = s.length -1
while (i < j){
if (s[i++].lowercaseChar() != s[j--].lowercaseChar()) return false
}
return true
}
}
I get this error
Not sure whats going on or where I messed up. Any help is appreciated.
In addition to the array problem identified in Tenfour04's answer, the code has an additional problem:
split("") splits the string into individual characters, not just individual words.
If you debug it, you'll find that isPalindrome3() is being called first on an empty string, then on "S", then on "i", and so on.
That's because the empty string "" matches at every point in the input.
The easiest fix is to call split(" "), which will split it at space characters.
However, that might not do exactly what you want, for several reasons: it will include empty strings if the input has runs of multiple spaces; it won't split at other white space characters such as tabs, newlines, non-breaking spaces, en spaces, etc.; and it will include punctuation such as commas and full stops. Splitting to give only words is harder, but you might try something like split(Regex("\\W") to include only letters, digits, and/or underscores. (You'll probably want something more sophisticated to include hyphens and apostrophes, and ensure that accented letters etc. are included.)
There's a further issue that may or may not be a problem: you don't specify a minimum length for your palindromes, and so words like a match. (As do empty strings, if the split produces any.) If you don't want the result to be 0 or 1, then you'll also have to exclude those.
Also, the code is currently case-sensitive: it would not count "Abba" as a palindrome, because the first A is in upper case but the last a isn't. If you wanted to check case-insensitively, you'd have to handle that.
As mentioned in a comment, this is the sort of thing that should be easy to test and debug. Short, self-contained functions with no external dependencies are pretty easy to write unit tests for. For example:
#Test fun testIsPalindrome3() {
// These should all count as palindromes:
for (s in listOf("abcba", "abba", "a", "", "DDDDDD"))
assertTrue(isPalindrome3(s))
// But these shouldn't:
for (s in listOf("abcbb", "Abba", "a,", "abcdba"))
assertFalse(isPalindrome3(s))
}
A test like that should give you a lot of confidence that the code actually works. (Especially because I've tried to include corner cases that would spot all the ways it could fail.) And it's worth keeping unit tests around once written, as they can verify that the code doesn't get broken by future changes.
And if the test shows that the code doesn't work, then you have to debug it! There are many approaches, but I've found printing out intermediate values (whether using a logging framework or simply println() calls) to be the simplest and most flexible.
And for reference, all this can be rewritten much more simply:
fun String.leastP() = split(Regex("\\W"))
.filter{ it.length >= 2 && it.isPalindrome() }
.minOfOrNull{ it.length }
private fun String.isPalindrome() = this == reversed()
Here both functions are extension functions on String, which makes them a bit simpler to write and to call. I've added a restriction to 2+ characters. And if the input is empty, minOfOrNull() returns null instead of throwing a NoSuchElementException.
That version of isPalindrome() isn't quite as efficient as yours, because it creates a new temporary String each time it's called. In most programs, the greater simplicity will win out, but it's worth bearing in mind. Here's one that's longer but as efficient as in the question:
private fun String.isPalindrome()
= (0 until length / 2).all{ i -> this[i] == this[length - i - 1]}
Your newArray is a read-only list. When you call plus on it, the function does not modify the original list (after all, it is read-only). The List.plus() function returns a new list, which you are promptly discarding by not assigning it to any variable or property.
Then it crashes because it is unsafe to call minOf on an empty list.
Two different ways to fix this:
Make the newArray variable a var and replace newArray.plus(j) with newArray += j. The += operator, when used on a read-only list that is assigned to a mutable var variable, calls plus() on it and assigns the result back to the variable.
Initialize newArray as a MutableList using mutableListOf() and replace newArray.plus(j) with newArray += j. The += operator, when used with a MutableList, calls add() or addAll() on the MutableList, so it directly changes the original instance.
I didn’t check any of your logic. I’m only answering the question about why it’s crashing.
But as Gidds points out, the logic can be simplified a ton to achieve the same thing you’re trying to do using functions like filter(). A few odd things you’re doing:
Putting the result ofstring.split("") in a list for no reason
Using "" to split your string so it’s just a list of one-character Strings instead of a list of words. And you’re ignoring punctuation.
Filling newArray with indices so minOf will simply give you the first index that corresponded with being a palindrome, so it will always be 0.
Here’s how I might write this function (didn’t test it):
fun leastP(s: String): Int {
return s.split(" ")
.map { it.filter { c -> c.isLetter() } }
.filter { isPalindrome3(it) }
.minOfOrNull { it.length } ?: 0
}
I have these three implementations, that (should) do essentially the same: return the current position of Android exoplayer or 0 as integer.
But only nr. 1 works. Nr. 2 and nr.3 always return 0, even though player is instantiated. Is that expected behaviour?
1.
private var playbackPosition = 0
get() {
return if (player == null) 0 else player?.currentPosition?.toInt() as Int / 1000
}
2.
private var playbackPosition = if (player == null) 0 else player?.currentPosition?.toInt() as Int / 1000
3.
private var playbackPosition = when(player) {
null -> 0
else -> player?.currentPosition?.toInt() as Int / 1000
}
Number 1 are an implementation of a get function and invoked every time you access the variable.
Number 2 and 3 initialize a variable and the right side are only invoked once at creation time of the variable. Means the playback position is calculated only once.
The behavior works like designed. If you need the new position every time you access the variable you have to use an own getter function.
Because of the question, I assume you're not that familiar with Kotlin and/or Java, so I'm going to explain the difference between the two.
First of all, you need to understand the difference between a function and a variable/constant. A function can have a varying result when it's called (assuming it's not a void/Unit), but a variable has a fixed result until it's updated. Take this:
var toggle = Random().nextBoolean()
var dependent = if(toggle) 0 else 1
toggle = !toggle
If you print the variable before and after the toggle is switched, the variable will not change. When it's been assigned, it stays with that value until something updates it. So if you add print statements, it will be the same. Let's expand on that:
var toggle: Boolean = Random().nextBoolean()
fun someFunction() : Int = (if(toggle) 0 else 1).also { toggle = !toggle }
The also block here is an extension function that lets you do stuff, but still return the variable it's called on. Here, either 1 or 0 is returned, and the toggle is inverted. If you call this two times, you'll see a different result. This is because you get a different value based on a condition. Again, you see the value doesn't change even though the toggle does.
TL;DR: Variables have a given value until changed. Methods returning values can change based on conditions, because it's updated every time it's called.
Now, what does this mean for your code?
First of all, for the first snippet, you should use val instead. Kotlin is really nice like that; if you override the getter of a val, you don't need to initialize it. It's called backing fields.
Anyways, this:
private val playbackPosition
get() {
return if (player == null) 0 else player?.currentPosition?.toInt() as Int / 1000
}
returns a value depending on the player variable when it is called. Where as the other examples:
private var playbackPosition = if (player == null) 0 else player?.currentPosition?.toInt() as Int / 1000
private var playbackPosition = when(player) {
null -> 0
else -> player?.currentPosition?.toInt() as Int / 1000
}
Set the value when they're defined. You could change those to a val too; they aren't automatically re-assigned.
Initial assignment, that being the code you have there, is only run once, and that's when the class is initialized. If the variable is inside a method, the variable is initialized when the method is called. lateinit vars can be set at a later time, but initial assignment is only run once. For any changes you'll need to update it.
However, this is where methods come in handy. Depending on what you have, you could also create a backing field, a "cache" in a way. This isn't necessary unless object creation is heavy. You don't need to worry about this for something as simple as integers. Using a method that returns the value (in your case, the getter), is kinda like doing this:
var x: Int = updateValue()
fun updateValue() : Int = if ... // alternatively does x = instead of returning an int
...
x = updateValue()
x.let { foo bar }
Although that is a considerably harder way of doing stuff.
But only Nr. 1 works. Nr. 2 and Nr.3 always return 0, although player is instantiated.
If you get 0 all the time for 2 and 3, that means player == null when the variables were intiailized, but it wasn't null when the getter for the first example was called.
Is that expected behaivour?
Considering the code, yes. It's by design.
TL;DR: Again, variables aren't automatically updated when a creating condition (i.e. player == null) changes. You'll either need to manually update it, or use methods over variables.
This is what I have and what I want to achieve:
I have a class which has a mutableList as a field.
I want to find a specific element inside that list and change it.
This is what I've tried so far:
This is the functional statement I was hoping would have worked, after I've also put it in an Extension function:
fun Classroom.setNewParameters(id: String, modifiedName: String) {
this.students.filter { l -> l.id == id }
.map { l -> l.name = modifiedName }
.toList()
}
But the list students appears to be unchanged after this function is called.
I found an "ugly" solution with the code below:
fun Classroom.setNewParameters(id: String, modifiedName: String) {
for (l : Student in this.students) {
if (l.id == id) {
l.name = modifiedName
break
}
}
}
Still tho, I'd really like to know why the first block of code behaves like it does and doesn't actually have any effect on the list.
You can think of map as a way to transform input to get new output. Normally it should not mutate state inside, in other words it should be a function without side effects to pursue maintainability
In your case you clearly want to mutate elements, for that you might want to use that code snippet:
fun Classroom.setNewParameters(id: String, modifiedName: String) {
this.students.filter { l -> l.id == id }
.onEach { l -> l.name = modifiedName }
}
Also, even you used map incorrectly it should must modify field l.name (unless you have implemented you own delegates or getter/setter). Try to debug set breakpoint on this.students.filter { l -> l.id == id } and see if there are any items left after filtering
Noob here but I did just see something related to this the other day.
Is there a reason you wouldn't just check to see if your array contains the old value, return the element id and then assign your new value to that id?
I guess I'm just pointing out that this could be accomplished with a "value in array" type search... but I'm still too new to know the pros and cons of using it vs map.
Kind of like this below, which I got from Kotlin - Idiomatic way to check array contains value
"value" in array
Which translates into the Java API:
array.contains("value")
So I'd check for the old value in the array, return it's index and then reassign that index with the new value.
I have two queries against a particular table in Go - one to retrieve a single item and the other to return a list. The first one uses sql.DB.QueryRow because it only needs to retrieve a single row, and the second one uses sql.DB.Query to return a few different results.
The problem is that serialization takes some work and I'd like to DRY it up by having a single method that scans from a database row and reads it into a Go type. My code right now looks like:
// Some type which varies considerably from its DB representation, and takes some effort to serialize.
type Foo struct {
Baz *Baz
Board [8][8]int
}
// Get one foo by its id
func GetFoo(id int) {
row := db.QueryRow("select * from foo where id = ?", id)
// Work that's duplicated from below...
var foo Foo
row.Scan(&foo.blah, &foo.etc)
// Do more work to serialize the type...
}
// Get all of the fooes
func GetFooes() {
rows, err := db.Query("select * from foo")
for rows.Next() {
// Work that's duplicated from above...
var foo Foo
rows.Scan(&foo.blah, &foo.etc)
// Do more work to serialize the type...
}
}
However combining row.Scan and rows.Scan is proving to be a little tricky. I thought I could use something like:
func serializeFoo(scanner sql.Scanner) (*Foo, error) {
}
though sql.Scanner takes a single (value interface{}) and not a list of (...value interface{}).
Any advice here? Another solution would be to convert the single QueryRow call into a db.Query.
db.QueryRow is a convenience function. There is no reason to use it unless it will save on typing/code-complexity. In this case, it doesn't so I recommend you just use db.Query.
See http://golang.org/src/pkg/database/sql/sql.go?s=25740:25802#L966 for more details
As you mentioned, neither Row nor Rows implement the Scanner interface. Scanner is used for arguments of the variatic scan functions.
If you want to have a parameter that allows either Row or Rows, you need to make your own interface For example:
func serializeFoo(scanner interface{Scan(dest ...interface{}) error}) (*Foo, error) {
}
I have a member variable that tells units for a value I have measured like centimeters,kilometers,seconds,hours etc.
Now these are enums,
When I display a corresponding string, I have created a method that returns corresponding string for these enums.
Unlike Java, enums here cant have other properties associated with them.
So I have to explicitly do a if-else-if chain or a switch case to return the correct string.
I am new to Objective C. any good practice that I should be following in such scenarios ?
afaik Objective-C enums are just old-school C enums... so maybe you can use an integer value for them?
I guess if your enum values started at 0 and increased you could use some sort of array access:
const char *distanceUnitToString2(enum DistanceUnit unit)
{
const char *values[] = {
"cm",
"m",
"km"
};
// do some sanity checking here
// ...
return values[unit];
}
But this feels a little flaky to me. What if you have negative values, or you are using bitmask-style enum values like 1 << 8? You are going to end up using a very large array.
You also could use a switch and improve it a little with a macro. Something like this:
const char *distanceUnitToString(enum DistanceUnit unit)
{
#define CASE(UNIT, STRING) case (UNIT): return (STRING)
switch (unit) {
CASE(kCentimeters, "cm");
CASE(kMeters, "m");
CASE(kKiloMeters, "km");
default:
// should not get here
assert(0);
break;
}
#undef CASE
}
But you don't really save that much vs. not using the macro.
Martin James's comment is the right answer. And use a definition of the enum like:
enum units { cm = 0, m, km };
that way you can be sure that your enum translates to the correct index values.