What is the canonical way to convert an Array<Byte> to a ByteArray - arrays

If have an Array and want to convert it to a ByteArray, how should I go about it? The following for instance fails:
var srcArray = Array<Byte>(10, { 0 })
var tgtArray: ByteArray = srcArray as ByteArray
I do realize though that specialized classes such as ByteArray are:
... not related to the Array class and are compiled down to Java’s primitive arrays for maximum performance.
So, the fact that my approach fails shouldn't surprise me - but what is the canonical way to make the conversion? Simply iterate through srcArray and populate tgtArray one index at a time - or is there a more elegant solution I'm missing?

I don't see any built-in functions apart from the obvious loop-based approach. But you could define an extension function like this yourself:
fun Array<Byte>.toPrimitive(): ByteArray {
val tgtArray: ByteArray = ByteArray(this.size())
for (i in this.indices) {
tgtArray[i] = this[i]
}
return tgtArray
}
fun test() {
val srcArray = Array<Byte>(10, { 0 })
val tgtArray: ByteArray = srcArray.toPrimitive()
}

Kotlin has this in the stdlib as an extension function Array<Byte>.toByteArray()
val srcArray = Array<Byte>(10, { 0 })
val tgtArray = srcArray.toByteArray()
(Note: I changed your var to val which is more common in Kotlin to use read-only values)
You will see similar ones for other primitive data types that have array implementations. You can see them all in the Kotlin documentation for Array extension functions.

Related

Map modify array of objects in Swift 2.2 (3.0)

I want to be able to modify my array of objects using map in Swift of the fly, without looping through each element.
Before here were able to do something like this (Described in more details here:
gnomes = gnomes.map { (var gnome: Gnome) -> Gnome in
gnome.age = 140
return gnome
}
Thanks for Erica Sadun and others, new proposals have gone through and we're now getting rid of C-style loops and using var inside the loop.
In my case I'm first getting a warning to remove the var in then an error my gnome is a constant (naturally)
My question is : How do we alter arrays inside a map or the new styled loops for that matter to be fully prepared for Swift 3.0?
If you want to keep that syntax, just use a (mutable) temporary variable
gnomes = gnomes.map { (gnome: Gnome) -> Gnome in
var mutableGnome = gnome
mutableGnome.age = 140
return mutableGnome
}
(Below follows the case where Gnome is a reference type; a class -- since you haven't showed us how you've defined Gnome. For the case where Gnome as value type (a struct), see #vadian:s answer)
The removal of var will not effect using .map to mutate mutable members of an array of reference type objects. I.e., you could simply use your old approach (omitting however, the var in the .map closure signature).
class Gnome {
var age = 42
}
var gnomes = [Gnome(), Gnome(), Gnome()]
gnomes = gnomes.map {
$0.age = 150
return $0
}
/* result */
gnomes.forEach { print($0.age) } // 3x 150
However, in case you just want to modify your original array rather than assigning the result of .map to a new array, .forEach might be a more appropriate choice than .map.
gnomes.forEach { $0.age = 140 }
/* result */
gnomes.forEach { print($0.age) } // 3x 140
Given:
struct Gnome {
var age: Int = 0
}
var gnomes = Array(count: 5, repeatedValue: Gnome())
... there are two decent options. The first is as #vadian put it:
gnomes = gnomes.map{
var gnome = $0
gnome.age = 70
return gnome
}
Whilst the second keeps control over "ageing" private and simplifies mapping at the point of call:
struct Gnome {
private(set) var age: Int = 0
func aged(age: Int) -> Gnome {
var gnome = self
gnome.age = age
// any other ageing related changes
return gnome
}
}
gnomes = gnomes.map{ $0.aged(140) }
Of course, reference types still have their place in programming, which may well be a better fit in this case. The friction we are experiencing here suggests that we are trying to treat these structures as if they were objects. If that is the behaviour you need, then you should consider implementing Gnome as a class.

Having array problems in Swift

I am learning how to build apps and working with Swift for this project.
I had a buddy help me pull data in from a website and it looks like he created classes with variables and mapped them to certain extensions (IE "Username") so when I call the variable data such as profile I would call it. The below uses luck_30 able to store "Stats.luck_30"
luck_30.text = profile.luck_30
So inside one of my variables that is in this "Profile" class is setup into an array. I can pull the array out of the class, but I can't seem to do for while statement replacing the [#] with a variable from the for command.
func aliveWorkers(profile: Profile) -> NSNumber{
var myworkers : Array = profile.workers!
//this test works and returns the proper value
var testworker: NSNumber = myworkers[0].alive!
println("The satus of the test worker is " + testworker.description)
/* This code is giving error "Could not find member alive" it does not ifor var
for ifor in myworkers{
var thisworker: NSNumber = myworkers[ifor].alive! as NSNumber
}
*/
return 42
}
Your variable ifor is not a counter, it is an actual object. You could do something like this:
for worker in myWorkers {
let workerIsAlive = worker.alive!
}
Alternatively, if you need the index,
for i in 0 ..< myWorkers.count {
let worker = myWorkers[i]
let workerIsAlive = worker.alive!
}
If you need both:
for (i, worker) in enumerate(myWorkers) {
let workerIsAlive = worker.alive!
}
And as a matter of style, I would stay away from NSNumber and use Int or Bool or whatever the data actually is. Also, it looks like the alive variable should not be optional, as you're unwrapping it everywhere. To avoid "mysterious" crashes later, you may want to think about making it a non-optional type.
when using a for in loop, your loop variable isn't an index, its the objects you're looping through. so..
func aliveWorkers() {
var myworkers = [1, 2, 3]
//this test works and returns the proper value
let testworker = myworkers[0]
print("The satus of the test worker is \(testworker)")
for ifor in myworkers {
print(ifor)
}
}
Notice a few things... you don't need to use + to concatenate those strings. you can just use string interpolation. \(variable) inserts the value of variable in the string.
Try to use let instead of var when you don't change the variable. You don't need to explicitly define type on variables either.

what is magic of Scala Array.apply

From array.scala of scala-2.10.4, The Array is defined as
final class Array[T](_length: Int) extends java.io.Serializable with java.lang.Cloneable {
/** The length of the array */
def length: Int = throw new Error()
def apply(i: Int): T = throw new Error()
def update(i: Int, x: T) { throw new Error() }
override def clone(): Array[T] = throw new Error()
}
Please note, the apply method will throw an exception! And for the accompany object Arrry, I find the following codes:
def apply[T: ClassTag](xs: T*): Array[T] = {
val array = new Array[T](xs.length)
var i = 0
for (x <- xs.iterator) { array(i) = x; i += 1 }
array
}
I know there is an implicit parameter which is ClassTag[T], what make me surprised is how
new Array[T] (xs.length)
is compiled. By decompiling the Array.class, I find that line is translated to :
public <T> Object apply(Seq<T> xs, ClassTag<T> evidence$2)
{
// evidence$2 is implicit parameter
Object array = evidence$2.newArray(xs.length());
...
}
I am really confused by this kind of translation, what is the rule under the hood?
Thanks
Chang
The Scala Array Class is just a fake wrapper for the runtime so you can use arrays in Scala. You're probably confused because those methods on the Array class throw exceptions. The reason they did this is so that if you actually end up using the fake class it blows up since really it should be using the java runtime array, which does not have a proper container class like Scala. You can see how the compiler handles it here. When your using arrays in Scala you're probably also using some implicits from predef like ArrayOps and WrappedArray for extra helper methods.
TLDR: Scala compiler magic makes arrays work with the java runtime under the hood.
On the JVM arrays are exempt from type-erasure, e.g. at runtime instead of Array[_] there is a difference between Array[Int], Array[String] and Array[AnyRef] for example. Unlike Java, Scala can handle this mostly transparently, so
class Foo {
val foo = new Array[Int](123)
}
has a direct byte-code invocation for creating the integer array, whereas
class Bar[A](implicit ev: reflect.ClassTag[A]) {
val bar = new Array[A](123)
}
is solved by using the implicit type evidence parameter of type ClassTag[A] so that at runtime the JVM can still create the correct array. This is translated into the call you saw, ev.newArray(123).

Using functions in arrays Swift

i use the following function to retrieve a random person from an array:
func getRandomPerson() -> String{
if(personArray.isEmpty){
return ""
} else {
var tempArray: [String] = []
for person in personArray{
tempArray += [person.getName()]
}
var unsignedArrayCount = UInt32(tempArray.count)
var unsignedRandomNumber = arc4random_uniform(unsignedArrayCount)
var randomNumber = Int(unsignedRandomNumber)
if tempArray.isEmpty {
return ""
} else {
return tempArray[randomNumber]
}
}
}
I would like to use this function inside an array of strings, Like this:
var theDares: [String] = ["Dare1 \(getRandomPerson())", "Dare2", "Dare3", "Dare4", "Dare5"]
But when i use the functions, it only runs the function once. Can you make the function run everytime you use the "Dare1" in this instance.
Thanks in advance
I think you are asking if you can set up your array so every time you fetch the object at index 0, it re-builds the value there.
The short answer is no. Your code is creating an array of strings, and the item at index 0 is built ONCE using a function call.
However, it is possible to make a custom class implement the subscript operator. You could create a custom object that looks like an array and allows you to index into it using an Int index. In response to the index operator you could run custom code that built and returned a random string.
Since it sounds like you're a beginning programmer creating a custom class the implements the subscript operator might be beyond your current abilities however.
Try like this:
let personArray = ["John", "Steve", "Tim"]
var randomPerson: String {
return personArray.isEmpty ? "" : personArray[Int(arc4random_uniform(UInt32(personArray.count)))]
}
println(randomPerson) // "Steve"

Can generic list utilities use Vectors (AS3)?

Using Object or * as a type for a Vector doesn't provide generic functionality (like List in Java). Witness:
public static function someGenericVectorUtil (value:Vector.<*>) :void {
// do stuff to/with the Vector
}
var someVector:Vector.<Number>;
someGenericVectorUtil(someVector); // compile-time implicit coercion error
So, perhaps we redefine the utility method to accept an Array. But there's no easy way to convert Vectors going into the utility to Arrays, nor an easy way to pack them back in afterwards, resulting in code like this:
public static function someGenericArrayUtil (value:Array) :void {
// do stuff to/with the formerly-known-as-Vector
}
var someVector:Vector.<Number>;
var tempArray:Array = new Array(someVector.length);
for (var i:uint=0; i<someVector.length; i++) {
tempArray[i] = someVector[i];
}
someGenericVectorUtil(tempArray);
someVector = Vector.<Number>([tempArray]);
Needless to say, that's pretty hideous. Okay, so let's move the Vector-Array-Vector nonsense into a utility:
public static function vectorToArray (Vector.<*>) :Array {
// oh wait....that Vector.<*> param is useless,
// as demonstrated earlier.
}
Any way to straighten out this mess? Or should I just stop using Vectors when I think I might need to run them through generic utilities? (Obviously, also not really much of an option...)
public static function someGenericVectorUtil (value:Vector.<*>) :void {
// do stuff to/with the Vector
}
var someVector:Vector.<Number>;
someGenericVectorUtil(Vector.<*>(someVector));
^ it works. Also try with Array.
This is not an answer but more a long comment to #Lukasz's answer.
The problem with his answer is that you're actually creating a new Vector, so you need to return the Vector from someGenericVectorUtil and re-cast it. E.g. try:
var v:Vector.<int> = Vector.<int>([1,2,3]);
trace( v == Vector.<int>( Vector.<*>( v ) ) ); // traces false
That code just creates a simple Vector of ints, then compares it with a version of itself casted (first to *, then back to int). If you trace the Vectors out, they'll trace identical, but the actual Vectors references themselves aren't the same object. Thus if you have a utility function that modifies the Vector (e.g. a shuffle or randomise function), nothing will change.
E.g:
var v:Vector.<int> = Vector.<int>([1,2,3]);
trace( v ); // traces "1,2,3"
// shuffle() randomises the elements in a vector - this first call won't work
// as the cast creates a new vector
VectorUtil.shuffle( Vector.<*>( v ) );
trace( v ); // traces "1,2,3"
// we need to recast it back, and change shuffle() to return the vector
v = Vector.<int>( VectorUtil.shuffle( Vector.<*>( v ) ) );
trace( v ); // traces "3,1,2"
As you can see, it starts to get a bit ugly towards the end, and if you're keeping track of the Vector anywhere else, you'll need to update the references, but it's the only solution that I've found so far :S

Resources