I am using Room Database in my Android App. One of the columns represents volume of drink in milliliters [ml]. I wonder what is the proper way of giving user option to choose/change units to [cl] or other.
Should I make a settings option to choose unit, and then convert all values in my database?
Should I store for example [ml] and then convert values depending on units selected by user?
What is the most efficient way? What will be less resources consuming?
Are You guys having some good open source examples/tutorials/code snippets?
It really depends on the volume and complexity of your conversions.
If you only have a single value (ML) and need to convert it to another value (CL, OZ...) then you can just set a base unit to the DB and convert the value in real time just before displaying them to the user.
If you feel this will get out of hand since you'll have many value types and you'll have a problem keeping track on all of them you can do the conversion in the DB that will cause some overhead on the select queries.
for example, you have this table:
ID unit val
--- --- ---
1 ML 960
2 ML 4112
3 KG 70
4 KG 35
5 C 37
You'll always keep base units in the DB the same meaning you will not mix them with F, OZ and LBS.
You can convert the units in your select query:
SELECT id, unit, val,
case when unit = 'ML' then val * 0.033
when unit = 'KG' then val / 2.205
when unit = 'C' then val * 9/5 + 32
end as result
FROM tbl
In both cases, since this is an Android app the work will be done via SQLite or the app itself.
Personally, I would not mix units on the same table because it would add a layer of complexity to later sort, compare and retrieve them.
Hope that helped.
Related
I have a n x 2 array or 2 independent onedimensional arrays but connected. I would like to sort one of the vectors (or one of the 2 columns of the n x 2 array) and sort the other accordingly.
It’s no use saying that I should create a class and make a class array, because I want to have ready access to the 2 vectors.
This is scientific programming, so I don't want to have to extract number arrays from class arrays. It is very inefficient.
I believe that or I will have to do the sorting by hand, because apparently I cannot use a comparator function model because it apparently does not give me access to the indexes of an individual value exchange, that is being made depending on the result of the comparison.
Is there no way or is there a good solution to this problem?
(Moved from https://softwareengineering.stackexchange.com/questions/406813/how-to-implement-fnv-1a-in-sqlite)
I'm trying to modify a SQLite query (in Android) to return its results in pseudorandom order. As in this question, the order needs to be stable over repeated queries (e.g. due to paging, screen rotation, etc.), so I can't just use ORDER BY RANDOM(). Instead I want to use a hash function that depends on a couple of input values that provide stability and sufficient uniqueness. (One of these values is a unique ID column of the table, which is a set of integers fairly close together; the other value is more like an session ID, also an integer, that remains invariant within this query.)
According to this well-researched answer, FNV-1 and FNV-1a are simple hash functions with few collisions and good distribution. But as simple as they are, FNV-1 and FNV-1a both involve XOR operations, as well as looping over the bytes of input.
Looping within each row of a query is pretty awkward. One could fake it by unrolling the loop, especially if only a few bytes are involved. I could make do with two bytes, combining LSBs from the two input values (val1 & 255 and val2 & 255).
XOR isn't supported directly in SQLite. I understand A ^ B can be implemented as (A | B) - (A & B). But the repetition of values, combined with the unrolling of the loop, starts to get unwieldy. Could I just use + (ignoring overflow) instead of XOR? I don't need very high quality randomness. The order just needs to look random to a casual observer over small-integer scales.
So I'm wondering if anyone has already implemented such a thing. Given how widely used this hash function is, it seems like there would likely already be an implementation for this situation.
Here's my attempt at implementing FNV-1a:
SELECT ..... ORDER BY (((fnvbasis + val1 & 255) * fnvprime) + val2 & 255) * fnvprime % range;
I'm ignoring the fact that in FNV, the XOR operation (which I've replaced with +) is only supposed to affect the lowest 8 bits of the hash value. I'm also ignoring any overflow (which I hope just means the upper bits, which I don't care about, are lost).
For fnvbasis I'll use 16777619, and for fnvprime I'll use 2166136261. These are the specified values for 32 bit input, since I don't see a specified value for 16 bit input. For range I'll use a prime number that's greater than the expected number of rows returned by this query.
So is this a reasonable way to approximate FNV-1a in a SQLite query? Is there a better, existing implementation? I.e. will it actually produce an ordering that looks pretty random to a casual user, despite my mutilating the operations of the real FNV-1a?
Inspired by comments from rwong and GrandmasterB on the previous attempt at this question before I moved it, I decided I could precompute the first iteration of FNV-1a's loop, i.e. the hash based on the unique ID column of the table. The precomputed column, fnv1a_step1, is set to
(fnvbasis ^ (ID & 0xFF)) * fnvprime
Because this value is precomputed on each row of the table separately, it can be supplied by the app and doesn't need to be expressed in SQLite; hence the use of ^ (XOR) above. Also, if ID is a string, we can compute an 8-bit hash value from it in Java or Kotlin as well. But we could even use
(fnvbasis + (RANDOM() & 0xFF)) * fnvprime
(back to using + if doing this in SQLite) because the value is only computed once, and therefore is stable even when computed from RANDOM().
The second iteration of the FNV-1a loop can be computed pretty simply in the ORDER BY clause of the query, using the current session ID, so it produces a different-but-stable ordering for each session:
ORDER BY (fnv1a_step1 + sessionId & 0xFF) * fnvprime % range;
I've implemented this in my app, and it seems to work, to my requirements. The order is stable within a session, but is different in each session.
Every country uses own measurement units, for example people in US measure temperature in F however Canada and most European countries in C. Same is applied for measurement weight, distance and so on.
I define measurement units in my application as
<string-array name="measure_units">
<item>lb</item>
<item>oz</item>
<item>cwt</item>
<item>ft</item>
<item>yd</item>
for default locale and then for France I define something like
<string-array name="measure_units">
<item>kg</item>
<item>ml</item>
<item>tn</item>
<item>dm</item>
<item>m</item>
So far so good, however it is a huge work to define the values for every country considering tons of duplicates. So I am thinking to introduce 2-4 basic measurement systems and specify values only for them, but how to implement it for Android? Is there any measurement systems mapping embedded in the OS? If there is no such functionality how do you deal with the problem?
SO this kind of thing is part of localization of an app. Generally the rule is- use one system internally in your app (generally metric, but anything will work). Convert to local units only right before display or right after data is input, never store data in anything but your internal format.
You might be able to find a library to do this for you, but its not built into Android or Java. Typically though you don't map every language to a length, temperature, etc. You do just what you suggested- build a couple of linked choices, and map Locales to a specific set of choices. If you pick metric as your default, you only need to do overrides for 2 or 3 countries- pretty much everyone uses metric.
I have a suggestion.
First store the values in international units. (Distance in m, Weight in kg, Temperature in C . . . etc). Then use some methods to convert international units to other units. When ever you need non-international units, use those methods to get the converted values. You can use an if statement or a switch to get the values accordingly.
As an example
if(/*international unit ?*/){
Log.D("International unit : ", temperature + "C");
}else{
Log.D("Non - International unit : ", getTemperatureInFahrenheit(temperature) + "F");
}
float getTemperatureInFahrenheit(float celsius){
return ((celsius * 9 / 5.0) + 32)
}
I have some 34 checkboxes on one Activity which i have to mark and unmark. and I want to save the status of the each checkbox.
I want this persistently. So should i have a sqlite table or preferences ?
If sqlite table is recommended, then what should be the ideal table structure design?
You could do it either by using SQLite or preferences. Though... what you want to do is kind of simple, so why would you care of creating a table, creating SQliteOpenHelper objects, designing a table, etc. The preferences approach is simpler.
So... what is most important here is how you identify your checkboxes. If you have just 34 static checkboxes (meaning they won't change its order) and they are into an array (which would be ideal), you have it easy.
As you might know, preferences editor does not allow to save arrays. So you have some choices:
Saving each state into a different preference slot (for instance: putBoolean("checkbox2", true); putBoolean("checkbox3", false); ect.)
Save all states into an String: putString("checkboxes_state", "10101011100011010"); this way you will have a String with 34 chars, each char represents a state.
If you want efficiency, you can represent all states with a simple long equals or lower than 17179869183. For instance putLong("checkboxes_state", 17179869183) would mean that all checkboxes are selected (because its binary representation is 1111111111111111111111111111111111). More examples:
12159999103 = 1011010100110010101101110001111111
1 = 0000000000000000000000000000000001, meaning that only the last checkbox is selected.
Edit
With regards to your question of why the last one is more efficient let me briefly explain. The first one implies using 34 preferences slots (actually I don't know how they are stored; hopefully, android team took care of performance). The second approach will use a 34 chars String; so, the minimum size that the String object would have is:
minimum String memory usage (bytes) = 8 * (int) ((34 * 2 + 45) / 8) = 113 bytes
Meaning that a String of that lengthen will take up at least 113 bytes. On the other hand, using just one long will take up 8 bytes only. The less bytes to work with, the faster your app will be (because Android will have to process and save less bytes).
I am wondering how would I be able to run a SQLite order by in this manner
select * from contacts order by jarowinkler(contacts.name,'john smith');
I know Android has a bottleneck with user defined functions, do I have an alternative?
Step #1: Do the query minus the ORDER BY portion
Step #2: Create a CursorWrapper that wraps your Cursor, calculates the Jaro-Winkler distance for each position, sorts the positions, then uses the sorted positions when overriding all methods that require a position (e.g., moveToPosition(), moveToNext()).
Pre calculate string lengths and add them into separate column. Then sort entired table by that that length. Add indexes (if you can). Then add extra filters for example you don't want to compare "Srivastava Brahmaputra" to "John Smith". The length are out of wack by way too much so exclude these kind of comparison by length as a percentage of the total length. So if your word is 10 characters compare it only to words with 10+-2 or 10+-3 characters.
This way you will significantly reduce the number of times this algorithm needs to run.
Typically in the vocalbulary of 100 000 entries such filters reduce the number of comparisons to about 300. Unless you are doing a full blown record linkage and then I would wonder why use Android for that. You would still need to apply probabilistic methods for that and calculate scores and this is not a job for Android (at least not for now).
Also in MS SQL Server Jaro Winkler string distance wrapped into CLR function perform much better, since SQL Server doesn't supprt arays natively and much of the processing is around arrays. So implementation in T-SQL add too much overhead, but SQL-CLR works extremely fast.