Ambiguous reference to member map when attempting to append/replace array element
Unfortunately, swift is not perfect and can not infer types at all times, this is why you are getting the ambiguous reference. Try userDicts.map {val -> [String:AnyObject] in
and swap out $0
for val
This will explicitly tell the map that the values coming in are [String:AnyObject]
, and should be able to return said type
Ambiguous reference to member map from concrete type
The error message is misleading. The real problem is that the map()
method applied to a dictionary does not return a new dictionary but an array, in your case [(String, String)]
,
See for example What's the cleanest way of applying map() to a dictionary in Swift? for a discussion of that topic.
Another problem is that NSString
is not converted to String
implicitly, i.e. NSString(data: data, ...)
should be replaced byString(data: data, ...)
.
Using the extension method
extension Dictionary {
init(_ pairs: [Element]) {
self.init()
for (k, v) in pairs {
self[k] = v
}
}
}
from the referenced thread you can return a new dictionary with
func convert(v: AnyObject) -> [String: String] {
let dict = v as! [CBUUID: NSData]
return Dictionary(dict.map { (uuid, data) in
(uuid.UUIDString, String(data: data, encoding: NSUTF8StringEncoding) ?? "")
})
}
Alternatively, change the return type to [(String, String)]
:
func convert(v: AnyObject) -> [(String, String)] {
return (v as! [CBUUID: NSData]).map { (uuid, data) in
(uuid.UUIDString, String(data: data, encoding: NSUTF8StringEncoding) ?? "")
}
}
Swift 3: sum value with group by of an array of objects
First of all Data
is reserved in Swift 3, the example uses a struct named Item
.
struct Item {
let value : Float
let name : String
}
Create the data array with your given values
let dataArray = [Item(value:10.5, name:"apple"),
Item(value:20.0, name:"lemon"),
Item(value:15.2, name:"apple"),
Item(value:45, name:"")]
and an array for the result:
var resultArray = [Item]()
Now filter all names which are not empty and make a Set
- each name occurs one once in the set:
let allKeys = Set<String>(dataArray.filter({!$0.name.isEmpty}).map{$0.name})
Iterate thru the keys, filter all items in dataArray
with the same name, sum up the values and create a new Item
with the total value:
for key in allKeys {
let sum = dataArray.filter({$0.name == key}).map({$0.value}).reduce(0, +)
resultArray.append(Item(value:sum, name:key))
}
Finally sort the result array by value desscending:
resultArray.sorted(by: {$0.value < $1.value})
---
Edit:
Introduced in Swift 4 there is a more efficient API to group arrays by a predicate, Dictionary(grouping:by:
var grouped = Dictionary(grouping: dataArray, by:{$0.name})
grouped.removeValue(forKey: "") // remove the items with the empty name
resultArray = grouped.keys.map { (key) -> Item in
let value = grouped[key]!
return Item(value: value.map{$0.value}.reduce(0.0, +), name: key)
}.sorted{$0.value < $1.value}
print(resultArray)
Generic Extension to Array Not Working
Give this a shot
extension Array where Element: Equatable {
func replaced (each valueToReplace: Element, with newValue: Element) -> [Element] {
var newArray = [Element]()
newArray.reserveCapacity(self.count)
for element in self {
let newElement = (element == valueToReplace) ? newValue : element
newArray.append(newElement)
}
return newArray
}
mutating func replace(each valueToReplace: Element, with newValue: Element) {
for (i, element) in self.enumerated() {
if element == valueToReplace { self[i] = newValue }
}
}
}
var j = [1,2,3,4,3,6,3,8,9]
var newArray = j.replaced(each: 3, with: 0)
It would be better to remove the redundancy by just making replaced
delegate to replace
:
extension Array where Element: Equatable {
func replaced(each valueToReplace: Element, with newValue: Element) -> [Element] {
var copy = self
copy.replace(each: valueToReplace, with: newValue)
return copy
}
mutating func replace(each valueToReplace: Element, with newValue: Element) {
for (i, element) in self.enumerated() {
if element == valueToReplace { self[i] = newValue }
}
}
}
React replace item in array
I had bit hard time understanding the question but is this what you want https://codesandbox.io/s/vj7vxw198y ? It still would need some work to allow adding same item multiple times if you want that.
Python-pandas: the truth value of a series is ambiguous
Let's reduce it to a simpler example. By doing for instance the following comparison:
3 == pd.Series([3,2,4,1])
0 True
1 False
2 False
3 False
dtype: bool
The result you get is a Series
of booleans, equal in size to the pd.Series
in the right hand side of the expression. So really what's happening here is that the integer is being broadcast across the series, and then they are compared. So when you do:
if 3 == pd.Series([3,2,4,1]):
pass
ValueError: The truth value of a Series is ambiguous. Use a.empty, a.bool(), a.item(), a.any() or a.all().
You get an error. The problem here is that you are comparing a pd.Series
with a value, so you'll have multiple True
and multiple False
values, as in the case above. This of course is ambiguous, since the condition is neither True
or False
.
So you need to further aggregate the result so that a single boolean value results from the operation. For that you'll have to use either any
or all
depending on whether you want at least one (any
) or all
values to satisfy the condition.
(3 == pd.Series([3,2,4,1])).all()
# False
or
(3 == pd.Series([3,2,4,1])).any()
# True
Truth value of a Series is ambiguous. Use a.empty, a.bool(), a.item(), a.any() or a.all()
The or
and and
python statements require truth
-values. For pandas
, these are considered ambiguous so you should use "bitwise" |
(or) or &
(and) operations:
df = df[(df['col'] < -0.25) | (df['col'] > 0.25)]
These are overloaded for these kinds of data structures to yield the element-wise or
or and
.
Just to add some more explanation to this statement:
The exception is thrown when you want to get the bool
of a pandas.Series
:
>>> import pandas as pd
>>> x = pd.Series([1])
>>> bool(x)
ValueError: The truth value of a Series is ambiguous. Use a.empty, a.bool(), a.item(), a.any() or a.all().
What you hit was a place where the operator implicitly converted the operands to bool
(you used or
but it also happens for and
, if
and while
):
>>> x or x
ValueError: The truth value of a Series is ambiguous. Use a.empty, a.bool(), a.item(), a.any() or a.all().
>>> x and x
ValueError: The truth value of a Series is ambiguous. Use a.empty, a.bool(), a.item(), a.any() or a.all().
>>> if x:
... print('fun')
ValueError: The truth value of a Series is ambiguous. Use a.empty, a.bool(), a.item(), a.any() or a.all().
>>> while x:
... print('fun')
ValueError: The truth value of a Series is ambiguous. Use a.empty, a.bool(), a.item(), a.any() or a.all().
Besides these 4 statements there are several python functions that hide some bool
calls (like any
, all
, filter
, ...) these are normally not problematic with pandas.Series
but for completeness I wanted to mention these.
In your case, the exception isn't really helpful, because it doesn't mention the right alternatives. For and
and or
, if you want element-wise comparisons, you can use:
numpy.logical_or
:>>> import numpy as np
>>> np.logical_or(x, y)or simply the
|
operator:>>> x | y
numpy.logical_and
:>>> np.logical_and(x, y)
or simply the
&
operator:>>> x & y
If you're using the operators, then be sure to set your parentheses correctly because of operator precedence.
There are several logical numpy functions which should work on pandas.Series
.
The alternatives mentioned in the Exception are more suited if you encountered it when doing if
or while
. I'll shortly explain each of these:
If you want to check if your Series is empty:
>>> x = pd.Series([])
>>> x.empty
True
>>> x = pd.Series([1])
>>> x.empty
FalsePython normally interprets the
len
gth of containers (likelist
,tuple
, ...) as truth-value if it has no explicit boolean interpretation. So if you want the python-like check, you could do:if x.size
orif not x.empty
instead ofif x
.If your
Series
contains one and only one boolean value:>>> x = pd.Series([100])
>>> (x > 50).bool()
True
>>> (x < 50).bool()
FalseIf you want to check the first and only item of your Series (like
.bool()
but works even for not boolean contents):>>> x = pd.Series([100])
>>> x.item()
100If you want to check if all or any item is not-zero, not-empty or not-False:
>>> x = pd.Series([0, 1, 2])
>>> x.all() # because one element is zero
False
>>> x.any() # because one (or more) elements are non-zero
True
Kotlin's List missing add, remove, Map missing put, etc?
Unlike many languages, Kotlin distinguishes between mutable and immutable collections (lists, sets, maps, etc). Precise control over exactly when collections can be edited is useful for eliminating bugs, and for designing good APIs.
https://kotlinlang.org/docs/reference/collections.html
You'll need to use a MutableList
list.
class TempClass {
var myList: MutableList<Int> = mutableListOf<Int>()
fun doSomething() {
// myList = ArrayList<Int>() // initializer is redundant
myList.add(10)
myList.remove(10)
}
}
MutableList<Int> = arrayListOf()
should also work.
Related Topics
Parametrized Unit Tests in Swift
Extend All Number Types in Swift
How to Handle Error with Realm During Writing
Bad_Access During Recursive Calls in Swift
Swift System Version Checking on Ubuntu
Nsmanagedobjectcontext's Propagatesdeletesatendofevent Set to False Causes Error on Save
Combined Watch Os and iOS Framework
Swift: Using Member Constant as Default Value for Function Parameter
How to Initialize a Struct with a Closure Parameter Like This
How to Change Font Size of Nstableheadercell
Error "[Sharesheet] Connection Invalidated" Error iOS13+ But Not on iOS 11.4
Decoding a Nested Array in Swift 4
Count Number of Instances of a Class Swift
Scrolltoitem at Indexpath at .Top Hides Cell Under Header When Sectionheaderspintovisiblebounds
Does Swift Allow Code Blocks Without Conditions/Loops to Reduce Local Variable Scope
Horizontal Scrolling in Spritekit (Vs. a Viewcontroller)
Swift Wkwebview: Can't Find Variable Error When Calling Method
Navigationlink Doesn't Work with New .Searchable Modifier on Swiftui 3.0