My enumeration is as follows:
for (i, poi) in enumerate(self.pois) {
//
}
I'd like to cast i and poi as (int, NSDictionary)
I tried many things, including:
for (i, poi) in enumerate(self.pois) as [(int, NSDictionary)]
Any idea?
this little package may be helpful for you:
let justAnArray: Array<(i: Int, poi: NSDictionary)> = Array()
// fill the array...
for temporaryTuple: (i: Int, poi: NSDictionary) in justAnArray {
// enumerate through elements...
println(temporaryTuple.i)
println(temporaryTuple.poi)
}
or
with typealias:
typealias CustomTuple = (i: Int, poi: NSDictionary)
var justAnArray: Array<CustomTuple> = Array()
// fill the array ...
for temporaryTuple: CustomTuple in justAnArray {
// enumerate through elements...
println(temporaryTuple.i)
println(temporaryTuple.poi)
}
What is the current type of poi? If poi is a Dictionary then the cast is simple.
for (i, poi) in enumerate(self.pois.map { $0 as NSDictionary }) {
println("\(i) : \(poi)")
}
Or you can do make the cast as the first line of the for loop.
for (i, poiDictionary) in enumerate(self.pois) {
let poi = poiDictionary as NSDictionary
println("\(i) : \(poi)")
}
If poi is an object, then you will need to call a method on poi to get the NSDictionary.
for (i, poi) in enumerate(self.pois.map { $0.toNSDictionary() }) {
println("\(i) : \(poi)")
}
Related
New in Go, couldn't find any intuitive way of doing that.
I have such piece of code
tx = getTx()
for _, record := range tx.a {
// do a lot with record.Important
}
for _, record := range tx.b {
// do a lot with record.Important
}
for _, record := range tx.c {
// do a lot with record.Important
}
And the following structs:
type Record1 struct {
// fields of Record1
Important string
}
type Record2 struct {
// fields of Record1
Important string
}
type TX struct {
a []Record1
b []Record1
c []Record2
}
Now the logical is to extract every for logic into the function:
func helper(records) { // Here is the problem
// do a lot with record.Important
}
Problem:
records is a []Record1 or []Record2 type. But it looks like Union types doesn't exists in Golang. So I thought I could pass []string into the helper, but cannot even find an elegant way to get something equivalent to map(lambda r: r.Important, tx.a). There is no high order map function, no list comprehesion. I am not convinced to use raw for loop to solve that.
One approach to do the loop across multiple types is to use interfaces together with generics. Have each Record type implement a getter method for the important field. Then declare an interface that includes that getter method in its method set. Then you can make your helper generic by declaring the interface as its type parameter.
func (r Record1) GetImportant() string { return r.Important }
func (r Record2) GetImportant() string { return r.Important }
type ImportantGetter interface {
GetImporant() string
}
func helper[T ImportantGetter](s []T) {
for _, v := range s {
_ = v.GetImportant()
}
}
Unless I'm misunderstanding your question, it seems like you want to extract all the values in column X from a set of records and then pass those values in as a slice to some function - I'm basing my assumption on your wish that go had something like map().
If what you're after is type-agnosticism, you could certainly use an interface approach like that suggested by mkopriva, but you aren't going to get out of using a for loop - iteration over list types is core to idiomatic go. If you need a mapping function, you're going to have to write one that performs the mapping you want.
I'd note that you do not need generics to do what mkopriva suggests, you can just use an interface without muddying the waters with generics go playground:
package main
import "fmt"
type Record1 struct {
Important string
}
type Record2 struct {
Important string
}
func (r Record1) GetImportant() string { return r.Important }
func (r Record2) GetImportant() string { return r.Important }
type ImportantGetter interface {
GetImportant() string
}
func helper(s []ImportantGetter) {
for _, v := range s {
fmt.Println(v.GetImportant())
}
}
func main() {
records := []ImportantGetter{Record1{Important: "foo"}, Record2{Important: "bar"}}
helper(records)
}
Another approach to the type-agnosticism, and one that's a bit more (IMHO) idiomatic for "I expect all of these types to have a common property," is to use struct embedding and type assertions to build your own Map() function up go playground:
type CommonFields struct {
Important string
}
type Record1 struct {
CommonFields
FieldSpecificToRecord1 string
}
type Record2 struct {
CommonFields
FieldSpecificToRecord2 int
}
func main() {
r1 := Record1{
CommonFields{Important: "I'm r1!"},
"foo",
}
r2 := Record2{
CommonFields{Important: "I'm r2!"},
5,
}
records := []interface{}{r1, r2, "this is not a valid record type"}
fmt.Println(Map(records))
}
func Map(source []interface{}) []string {
destination := make([]string, len(source))
for i, sourceRecord := range source {
if rr, ok := sourceRecord.(Record1); ok {
destination[i] = rr.Important
} else if rr, ok := sourceRecord.(Record2); ok {
destination[i] = rr.Important
} else {
destination[i] = "undefined"
}
}
return destination
}
You'd likely want to make your implementation of Map() accept an argument specifying the field to extract to conform to what you have in other languages, or possibly even just pass in a helper function which does most of the type-specific value extraction.
How can nested lists be declared in Kotlin?
I'm looking for something in the form of:
var nestedList:List = [1,[2,[3,null,4]],[null],5]
so that I can flatten it later on (result should be nestedList = [1, 2, 3, 4, 5]).
If you have nested arrays structure (for instance, val array: Array<Array<out Int?>> = arrayOf(arrayOf(1), arrayOf(2), arrayOf(3, null, 4))), you can just use flatten extension method:
println(array.flatten().filterNotNull())
All common collections can't maintain variable layers count, so with them you can make only something like Andrey Ilyunin wrote - val array: Array<Array<out Int?>>.
But I wrote class structure to help you with your goal. It is no another collection and you can't work with it like it is, but it can make any layers amount you want. It is totally generic, so you can put there not only Int.
First of all, we start with NestedArrayItem class, which represents single item or one more nested array:
class NestedArrayItem<T> {
private val array: ArrayList<NestedArrayItem<T>>?
private val singleItem: T?
constructor(array: ArrayList<NestedArrayItem<T>>) {
this.array = array
singleItem = null
}
constructor(singleItem: T?) {
this.singleItem = singleItem
array = null
}
fun asSequence(): Sequence<T?> =
array?.asSequence()?.flatMap { it.asSequence() } ?:
sequenceOf(singleItem)
override fun toString() =
array?.joinToString(prefix = "[", postfix = "]") ?:
singleItem?.toString() ?: "null"
}
Then class NestedArray that is just like top level container for all the layers:
class NestedArray<T> {
private val array: ArrayList<NestedArrayItem<T>> = arrayListOf()
fun add(value: T?) {
array.add(NestedArrayItem(value))
}
fun addNested(nestedArray: NestedArray<T>) {
array.add(NestedArrayItem(nestedArray.array))
}
fun flatten(): ArrayList<T?> = array.asSequence()
.flatMap { it.asSequence() }
.toCollection(arrayListOf())
override fun toString() = array.joinToString(prefix = "[", postfix = "]")
}
And to make it easier to write values I additionally wrote builder class for that:
class NestedArrayBuilder<T> private constructor(private val result: NestedArray<T>){
constructor(fillNestedBuilder: NestedArrayBuilder<T>.() -> Unit) : this(NestedArray()) {
NestedArrayBuilder(result).apply(fillNestedBuilder)
}
fun add(value: T?): NestedArrayBuilder<T> {
result.add(value)
return this
}
fun addArray(fillNestedBuilder: NestedArrayBuilder<T>.() -> Unit): NestedArrayBuilder<T> {
val nestedResult = NestedArray<T>()
val nestedArray = NestedArrayBuilder(nestedResult).apply(fillNestedBuilder)
.build()
result.addNested(nestedArray)
return this
}
fun build() = result
}
That's it! You can use it. I put here example how to use it:
val array = NestedArrayBuilder<Int> {
add(1)
addArray {
add(2)
addArray {
add(3)
add(null)
add(4)
}
}
addArray {
add(null)
}
add(5)
}.build()
assertEquals("[1, [2, [3, null, 4]], [null], 5]", array.toString())
assertEquals(arrayListOf(1, 2, 3, null, 4, null, 5), array.flatten())
I am converting Data bytes to sockaddr for getting sa_family_t
In ObjC, it is as below:
NSData * hostAddress;
- (sa_family_t)hostAddressFamily {
sa_family_t result;
result = AF_UNSPEC;
if ( (self.hostAddress != nil) && (self.hostAddress.length >= sizeof(struct sockaddr)) ) {
result = ((const struct sockaddr *) self.hostAddress.bytes)->sa_family;
}
return result;
}
In swift I am trying to convert it as below:
var hostAddress:Data?
private func hostAddressFamily() -> sa_family_t{
var result: sa_family_t = sa_family_t(AF_UNSPEC)
if (hostAddress != nil) && ((hostAddress?.count ?? 0) >= MemoryLayout<sockaddr>.size) {
// Generic parameter 'ContentType' could not be inferred
self.hostAddress!.withUnsafeBytes({ bytes in
bytes.withMemoryRebound(to: sockaddr.self, capacity: 1, {sockBytes in
result = sockBytes.pointee.sa_family
})
})
}
return result
}
Getting error : Generic parameter ‘ContentType’ could not be inferred
Look at the signature of Data.withUnsafeBytesType:
func withUnsafeBytes<ResultType, ContentType>(_ body: (Swift.UnsafePointer<ContentType>) throws -> ResultType) rethrows -> ResultType
This method is generic over ResultType and ContentType, and the ContentType is used in the argument of the closure body.
What compiler is trying to say is that it does not know what type bytes is of. Generally, to fix this type of errors, you'll want to annotate the type in the closure:
data.withUnsafeBytes { (_ bytes: UnsafePointer<...>) -> Void in ... }
Also, it's unlikely you'll need to bind the memory twice since NSData is untyped, and you already specifying a type to bind it to.
Putting it all together:
func hostAddressFamily() -> sa_family_t {
var result = sa_family_t(AF_UNSPEC)
guard
let hostAddress = hostAddress,
hostAddress.count >= MemoryLayout<sockaddr>.size
else {
return result
}
hostAddress.withUnsafeBytes { (_ bytes: UnsafePointer<sockaddr>) in
result = bytes.pointee.sa_family
}
return result
}
I'm trying to use rust-xcb to get a window's class given a window ID.
fn get_class(conn: &xcb::Connection, id: &i32) {
let window: xcb::xproto::Window = *id as u32;
let class_prop: xcb::xproto::Atom = 67; // XCB_ATOM_WM_CLASS from xproto.h
let cookie = xcb::xproto::get_property(&conn, false, window, class_prop, 0, 0, 2);
match cookie.get_reply() {
Ok(reply) => {
let x: &[std::os::raw::c_void] = reply.value();
println!("reply is {:?}", x[0]);
}
Err(err) => println!("err {:?}", err),
}
}
The documentation is kind of sparse and hasn't been incredibly helpful, though I did find this bit about the GetPropertyReply and of the xcb_get_property_reply_t it wraps.
I looked at this answer in JavaScript but I don't know what the ctypes equivalent in Rust is. I tried just casting the &[c_void] as a &str or String:
...
Ok(reply) => {
let len = reply.value_len() as usize;
let buf = reply.value() as &str;
println!("{}", buf.slice_unchecked(0, len)); // this seems redundant
}
...
but it returns
error: non-scalar cast: `&[_]` as `&str`
I tried casting the &[c_void] as a &[u8] and then collecting the Vec into a String, which sort of works:
...
Ok(reply) => {
let value : &[u8] = reply.value();
let buf : String = value.into_iter().map(|i| *i as char).collect();
println!("\t{:?}", buf);
}
...
but I'm now getting weird results. for example , when I use xprop on Chrome I see "google-chrome" but for me it is only showing "google-c", and "roxterm" is showing up as "roxterm\u{0}". I'm guessing "\u{0}" is something Unicode related but I'm not sure, and I don't know why stuff is being concatenated either. Maybe I have to check the reply again?
Here's my updated function:
fn get_class(conn: &Connection, id: &i32) -> String {
let window: xproto::Window = *id as u32;
let long_length: u32 = 8;
let mut long_offset: u32 = 0;
let mut buf = Vec::new();
loop {
let cookie = xproto::get_property(
&conn,
false,
window,
xproto::ATOM_WM_CLASS,
xproto::ATOM_STRING,
long_offset,
long_length,
);
match cookie.get_reply() {
Ok(reply) => {
let value: &[u8] = reply.value();
buf.extend_from_slice(value);
match reply.bytes_after() {
0 => break,
_ => {
let len = reply.value_len();
long_offset += len / 4;
}
}
}
Err(err) => {
println!("{:?}", err);
break;
}
}
}
let result = String::from_utf8(buf).unwrap();
let results: Vec<&str> = result.split('\0').collect();
results[0].to_string()
}
There were three main parts to this question:
I put xproto::get_property() in a loop so I could check reply.bytes_after() and accordingly adjust long_offset. I think with an appropriate long_length there will usually only be one read, but just being safe.
As #peter-hall said, converting &[u8] -> String should be done using String::from_utf8, which needs a Vec; so I let mut buf = Vec::new() and buf.extend_from_slice over the loop before creating the result string with String::from_utf8(buf).unwrap()
According to this random page WM_CLASS is actually two consecutive null-terminated strings, so I split the result by \0 and grab the first value.
I might've just been looking in the wrong place, but xcb has absolutely terrible documentation..
I have a list:
val someList = listOf(1, 20, 10, 55, 30, 22, 11, 0, 99)
And I want to iterate it while modifying some of the values. I know I can do it with map but that makes a copy of the list.
val copyOfList = someList.map { if (it <= 20) it + 20 else it }
How do I do this without a copy?
Note: this question is intentionally written and answered by the author (Self-Answered Questions), so that the idiomatic answers to commonly asked Kotlin topics are present in SO. Also to clarify some really old answers written for alphas of Kotlin that are not accurate for current-day Kotlin.
First, not all copying of a list is bad. Sometimes a copy can take advantage of CPU cache and be extremely fast, it depends on the list, size, and other factors.
Second, for modifying a list "in-place" you need to use a type of list that is mutable. In your sample you use listOf which returns the List<T> interface, and that is read-only. You need to directly reference the class of a mutable list (i.e. ArrayList), or it is idiomatic Kotlin to use the helper functions arrayListOf or linkedListOf to create a MutableList<T> reference. Once you have that, you can iterate the list using the listIterator() which has a mutation method set().
// create a mutable list
val someList = arrayListOf(1, 20, 10, 55, 30, 22, 11, 0, 99)
// iterate it using a mutable iterator and modify values
val iterate = someList.listIterator()
while (iterate.hasNext()) {
val oldValue = iterate.next()
if (oldValue <= 20) iterate.set(oldValue + 20)
}
This will change the values in the list as iteration occurs and is efficient for all list types. To make this easier, create helpful extension functions that you can re-use (see below).
Mutating using a simple extension function:
You can write extension functions for Kotlin that do an in place mutable iteration for any MutableList implementation. These inline functions will perform as fast as any custom use of the iterator and is inlined for performance. Perfect for Android or anywhere.
Here is a mapInPlace extension function (which keeps the naming typical for these type of functions such as map and mapTo):
inline fun <T> MutableList<T>.mapInPlace(mutator: (T)->T) {
val iterate = this.listIterator()
while (iterate.hasNext()) {
val oldValue = iterate.next()
val newValue = mutator(oldValue)
if (newValue !== oldValue) {
iterate.set(newValue)
}
}
}
Example calling any variation of this extension function:
val someList = arrayListOf(1, 20, 10, 55, 30, 22, 11, 0, 99)
someList.mapInPlace { if (it <= 20) it + 20 else it }
This is not generalized for all Collection<T>, because most iterators only have a remove() method, not set().
Extension functions for Arrays
You can handle generic arrays with a similar method:
inline fun <T> Array<T>.mapInPlace(mutator: (T)->T) {
this.forEachIndexed { idx, value ->
mutator(value).let { newValue ->
if (newValue !== value) this[idx] = mutator(value)
}
}
}
And for each of the primitive arrays, use a variation of:
inline fun BooleanArray.mapInPlace(mutator: (Boolean)->Boolean) {
this.forEachIndexed { idx, value ->
mutator(value).let { newValue ->
if (newValue !== value) this[idx] = mutator(value)
}
}
}
About the Optimization using only Reference Equality
The extension functions above optimize a little by not setting the value if it has not changed to a different instance, checking that using === or !== is Referential Equality. It isn't worth checking equals() or hashCode() because calling those has an unknown cost, and really the referential equality catches any intent to change the value.
Unit Tests for Extension Functions
Here are unit test cases showing the functions working, and also a small comparison to the stdlib function map() that makes a copy:
class MapInPlaceTests {
#Test fun testMutationIterationOfList() {
val unhappy = setOf("Sad", "Angry")
val startingList = listOf("Happy", "Sad", "Angry", "Love")
val expectedResults = listOf("Happy", "Love", "Love", "Love")
// modify existing list with custom extension function
val mutableList = startingList.toArrayList()
mutableList.mapInPlace { if (it in unhappy) "Love" else it }
assertEquals(expectedResults, mutableList)
}
#Test fun testMutationIterationOfArrays() {
val otherArray = arrayOf(true, false, false, false, true)
otherArray.mapInPlace { true }
assertEquals(arrayOf(true, true, true, true, true).toList(), otherArray.toList())
}
#Test fun testMutationIterationOfPrimitiveArrays() {
val primArray = booleanArrayOf(true, false, false, false, true)
primArray.mapInPlace { true }
assertEquals(booleanArrayOf(true, true, true, true, true).toList(), primArray.toList())
}
#Test fun testMutationIterationOfListWithPrimitives() {
val otherList = arrayListOf(true, false, false, false, true)
otherList.mapInPlace { true }
assertEquals(listOf(true, true, true, true, true), otherList)
}
}
Here's what I came up with, which is a similar approach to Jayson:
inline fun <T> MutableList<T>.mutate(transform: (T) -> T): MutableList<T> {
return mutateIndexed { _, t -> transform(t) }
}
inline fun <T> MutableList<T>.mutateIndexed(transform: (Int, T) -> T): MutableList<T> {
val iterator = listIterator()
var i = 0
while (iterator.hasNext()) {
iterator.set(transform(i++, iterator.next()))
}
return this
}
Here is a custom solution, with an example :
val sorted: MutableList<Pair<Double, T>> = ...
val groups: mutableListOf<List<T>>() = ...
sorted.forEachMutable { it ->
if (size + it.first <= maxSize) {
size += it.first
group += it.second
this.remove() // Removing from iterable !
}
}
Here is code for "forEachMutable" :
fun <T> MutableIterable<T>.forEachMutable(block: Removable<T>.(T) -> Unit): Unit {
val iterator: MutableIterator<T> = iterator()
val removable = Removable(iterator, block)
while (iterator.hasNext()) {
val item = iterator.next()
removable.action(item)
}
}
class Removable<T>(
private val iterator: MutableIterator<T>,
private val block: Removable<T>.(T) -> Unit) {
fun remove() =
iterator.remove()
fun action(item: T) {
block(item)
}
}
Maxime
Without having to write any new extension methods - yes, the functional paradigms are awesome, but they do generally imply immutability. If you're mutating, you might consider making that implicit by going old school:
val someList = mutableListOf(1, 20, 10, 55, 30, 22, 11, 0, 99)
for(i in someList.indices) {
val value = someList[i]
someList[i] = if (value <= 20) value + 20 else value
}
You can use list.forEach { item -> item.modify() }
This will modify each item in list while iterating.