How to check if a value in a dictionary has duplicates? - swift

The algorithm below checks to see if an array has at least two or more duplicates. It uses a dictionary to store the occurrences; the time complexity is linear because it has to traverse the dictionary to see if a key occurs twice. In swift, how can I look up a value to see if it occurs more than twice in constant time ?
func containsDuplicate(_ nums: [Int]) -> Bool {
var frequencyTable = [Int:Int]()
for num in nums {
frequencyTable[num] = (frequencyTable[num] ?? 0 ) + 1
}
for value in frequencyTable.values{
if value >= 2 {
return true
}
}
return false
}
containsDuplicate([1,1,2,3,3,3,3,4])

The second loop is not necessary if the first loop checks if the current element has already been inserted before, and returns from the function in that case:
func containsDuplicate(_ nums: [Int]) -> Bool {
var frequencyTable = [Int:Int]()
for num in nums {
if frequencyTable[num] != nil {
return true
}
frequencyTable[num] = 1
}
return false
}
Then it becomes apparent that we don't need a dictionary, a set is sufficient:
func containsDuplicate(_ nums: [Int]) -> Bool {
var seen = Set<Int>()
for num in nums {
if seen.contains(num) {
return true
}
seen.insert(num)
}
return false
}
This can be further simplified: The “insert and check if element was already present” operation can be done in a single call:
func containsDuplicate(_ nums: [Int]) -> Bool {
var seen = Set<Int>()
for num in nums {
if !seen.insert(num).inserted {
return true
}
}
return false
}
This is similar to the solution from this answer
return nums.count != Set(nums).count
but possibly more efficient: The function returns immediately when a duplicate element has been detected.
Finally we can make the function generic, so that it works with all arrays of a hashable type:
func containsDuplicate<T: Hashable>(_ array: [T]) -> Bool {
var seen = Set<T>()
for element in array {
if !seen.insert(element).inserted {
return true
}
}
return false
}
Example:
print(containsDuplicate([1,1,2,3,3,3,3,4])) // true
print(containsDuplicate(["A", "X"])) // false
Or as an extension for arbitrary collections of a hashable type:
extension Collection where Element: Hashable {
func containsDuplicate() -> Bool {
var seen = Set<Element>()
for element in self {
if !seen.insert(element).inserted {
return true
}
}
return false
}
}
print([1,1,2,3,3,3,3,4].containsDuplicate())
print(["A", "X"].containsDuplicate())

You just want to know if it has duplicate, you can use use set and compare the length.
func containsDuplicate(_ nums: [Int]) -> Bool {
return Set(nums).count != nums.count
}
like this examples, because the set remove the duplicate values.

Related

How can i fix the true or false in this code? [duplicate]

This question already has answers here:
Extending Array to check if it is sorted in Swift?
(13 answers)
Closed 3 months ago.
Write a function isIncreasing that takes a list of Ints and returns true if numbers are in increasing (equals OK) order. An empty list should result in true.
func isIncreasing(_ l: [Int]) -> Bool {
var flagreturn=true
if l.count == 0 {
flagreturn=true
} else {
for i: Int in l {
if l[i] < l[i + 1] {
flagreturn=true
}
else{
flagreturn=false
}
}
}
return flagreturn
}
Not sure if I implemented the true and false correctly in the code.
You can zip the sequence with itself dropping the first element and check if it all satisfy a condition like $0 <= $1:
func isIncreasing(_ l: [Int]) -> Bool {
zip(l, l.dropFirst()).allSatisfy { $0 <= $1 }
}
isIncreasing([1,2]) // true
isIncreasing([0,1,1,2]) // true
isIncreasing([0,1,1,2,1]) // false
Expanding on that you can extend sequence constraining its elements to Comparable an d create a generic property like areInIncreasingOrder:
extension Sequence where Element: Comparable {
var areInIncreasingOrder: Bool {
zip(self, dropFirst()).allSatisfy { $0 <= $1 }
}
}
Usage:
[1,2].areInIncreasingOrder // true
[1,2].dropFirst(2).areInIncreasingOrder // true
[0,1,1,2].areInIncreasingOrder // true
[0,1,1,2,1].areInIncreasingOrder // false

Getting error non-void return value in void function | Swift

I don't understand why I am getting the following error when executing this function:
error: unexpected non-void return value in void function
return [index, dic[value]!]
func findIndexes(_ nums: [Int], _ target: Int) -> [Int] {
var dic = [Int:Int]()
var answer: [Int] = []
nums.enumerated().forEach { index, value in
//the goal is to get the index of the value matching the difference
//check if current value == anything in dictionary
//MARK: Add the Index and Difference to Dictionary
let difference = (target - value)
if (dic.keys.contains(value) && !dic.values.contains(index)) {
return [index, dic[value]!]
}
dic[difference] = index
}
return []
}
print(findIndexes([0,11,15,2,7], 9))
I'm unclear what you're trying to do, but this is a version of what you are doing that compiles:
func findIndexes(_ nums: [Int], _ target: Int) -> [Int] {
var dic = [Int:Int]()
var answer: [Int] = []
for (index, value) in nums.enumerated() {
let difference = (target - value)
if (dic.keys.contains(value) && !dic.values.contains(index)) {
return [index, dic[value]!]
}
dic[difference] = index
}
return []
}
Why the difference? for...in is a loop. You can return from the surrounding function from within it, break out of it, etc. forEach loops implicitly but it is not a loop; it takes a closure, and you can't return out of that unless it's a closure that yields a return value, and this one doesn't; its type, as you can see from the docs, is (Self.Element) throws -> Void — and Void means "no return value".
If you insist on using forEach, you can do what you're trying to do with a bit of extra jiggery-pokery:
func findIndexes(_ nums: [Int], _ target: Int) -> [Int] {
var dic = [Int:Int]()
var answer: [Int] = []
nums.enumerated().forEach { index, value in
let difference = (target - value)
if (dic.keys.contains(value) && !dic.values.contains(index)) {
answer = [index, dic[value]!]
return
}
dic[difference] = index
}
return answer
}
I think that does what you're trying to do, but I'm not sure; it seems unnecessarily obscure. In my personal opinion, the way to program is to Say What You Mean (SWYM).

Adopting CollectionType (Collection) in Swift

I'm writing a graphics library to display data in a graph. Since most of the projects I do tend to have a large learning component in them, I decided to create a generically typed struct to manage my data set DataSet<T: Plottable> (note here that Plottable is also Comparable).
In trying to conform to MutableCollectionType, I've run across an error. I'd like to use the default implementation of sort(), but the compiler is giving the following error when trying to use the sorting function.
Ambiguous reference to member 'sort()'
Here's a code example:
var data = DataSet<Int>(elements: [1,2,3,4])
data.sort() //Ambiguous reference to member 'sort()'
The compiler suggests two candidates, but will not actually display them to me. Note that the compiler error goes away if I explicitly implement sort() on my struct.
But the bigger question remains for me. What am I not seeing that I expect the default implementation to be providing? Or am I running across a bug in Swift 3 (this rarely is the case... usually I have overlooked something).
Here's the balance of the struct:
struct DataSet<T: Plottable>: MutableCollection, BidirectionalCollection {
typealias Element = T
typealias Iterator = DataSetIterator<T>
typealias Index = Int
/**
The list of elements in the data set. Private.
*/
private var elements: [Element] = []
/**
Initalize the data set with an array of data.
*/
init(elements data: [T] = []) {
self.elements = data
}
//MARK: Sequence Protocol
func makeIterator() -> DataSetIterator<T> {
return DataSetIterator(self)
}
//MARK: Collection Protocol
subscript(_ index:DataSet<T>.Index) -> DataSet<T>.Iterator.Element {
set {
elements[index] = newValue
}
get {
return elements[index]
}
}
subscript(_ inRange:Range<DataSet<T>.Index>) -> DataSet<T> {
set {
elements.replaceSubrange(inRange, with: newValue)
}
get {
return DataSet<T>(elements: Array(elements[inRange]))
}
}
//required index for MutableCollection and BidirectionalCollection
var endIndex: Int {
return elements.count
}
var startIndex: Int {
return 0
}
func index(after i: Int) -> Int {
return i+1
}
func index(before i: Int) -> Int {
return i-1
}
mutating func append(_ newElement: T) {
elements.append(newElement)
}
// /**
// Sorts the elements of the DataSet from lowest value to highest value.
// Commented because I'd like to use the default implementation.
// - note: This is equivalent to calling `sort(by: { $0 < $1 })`
// */
// mutating func sort() {
// self.sort(by: { $0 < $1 })
// }
//
// /**
// Sorts the elements of the DataSet by an abritrary block.
// */
// mutating func sort(by areInIncreasingOrder: #noescape (T, T) -> Bool) {
// self.elements = self.elements.sorted(by: areInIncreasingOrder)
// }
/**
Returns a `DataSet<T>` with the elements sorted by a provided block.
This is the default implementation `sort()` modified to return `DataSet<T>` rather than `Array<T>`.
- returns: A sorted `DataSet<T>` by the provided block.
*/
func sorted(by areInIncreasingOrder: #noescape (T, T) -> Bool) -> DataSet<T> {
return DataSet<T>(elements: self.elements.sorted(by: areInIncreasingOrder))
}
func sorted() -> DataSet<T> {
return self.sorted(by: { $0 < $1 })
}
}
Your DataSet is a BidirectionalCollection. The sort() you're trying to use requires a RandomAccessCollection. The most important thing you need to add is an Indicies typealias.
typealias Indices = Array<Element>.Indices
Here's my version of your type:
protocol Plottable: Comparable {}
extension Int: Plottable {}
struct DataSet<Element: Plottable>: MutableCollection, RandomAccessCollection {
private var elements: [Element] = []
typealias Indices = Array<Element>.Indices
init(elements data: [Element] = []) {
self.elements = data
}
var startIndex: Int {
return elements.startIndex
}
var endIndex: Int {
return elements.endIndex
}
func index(after i: Int) -> Int {
return elements.index(after: i)
}
func index(before i: Int) -> Int {
return elements.index(before: i)
}
subscript(position: Int) -> Element {
get {
return elements[position]
}
set {
elements[position] = newValue
}
}
subscript(bounds: Range<Int>) -> DataSet<Element> {
get {
return DataSet(elements: Array(elements[bounds]))
}
set {
elements[bounds] = ArraySlice(newValue.elements)
}
}
}
var data = DataSet(elements: [4,2,3,1])
data.sort()
print(data.elements) // [1,2,3,4]
You don't actually need an Iterator if you don't want one. Swift will give you Sequence automatically if you implement Collection.

What is the Swift equivalent of C#/.NET/LINQ's Enumerable.All method?

I want a function that applies a given function to a sequence and returns true iff the given function returns true for every element of the sequence, like Enumerable.All from the C#/.NET/LINQ world.
Building up on Jon's answer: You can use contains()
instead of an (explicit) loop:
extension SequenceType {
func all(#noescape predicate: (Self.Generator.Element) throws -> Bool)
rethrows -> Bool {
return !(try contains { !(try predicate($0)) })
}
}
There isn't a built-in function to do this, but you can easily add your own as a protocol extension method:
extension SequenceType {
func all(#noescape predicate: (Self.Generator.Element) throws -> Bool)
rethrows -> Bool {
for i in self {
if !(try predicate(i)) { return false }
}
return true
}
}
and then use it on a sequence like:
let allPositive = [1, 2, 3].all { $0 > 0 }
Not sure if this helps, but you can achieve the same outcome using reduce. Here's a quick playground I put together to prove the concept:
let nums = [2, 2, 3, 4]
// Will only evaluate to true if all numbers are even.
let allEven = nums.reduce(true) {
if !$0 || $1 % 2 != 0 {
return false
}
return true
}

Swift: return number < 10

That's the code:
import Foundation
func hasAnyMatches(list: [Int], condition: Int -> Bool) -> Bool {
for item in list {
if condition(item) {
return true
}
}
return false
}
func lessThanTen(number: Int) -> Bool {
return number < 10
}
var numbers = [20, 19, 7, 12]
hasAnyMatches(numbers, condition: lessThanTen)
There is a return true within the if condition and a return false at the end of func hasAnyMatches(). Why is the return false needed?
Without explicitly "telling it" to return something, no function returns false "automatically". I am not writing in swift but I am sure if you take away the return false it'll throw a warning.
The lessThanTen simply returns a bool if the number is smaller than 10.
number < 10 is a statement checking if something is true or false. Hence the return type bool of lessThanTen
You can do like, for such condition.
let LESS_THAN_TEN = 1
let LESS_THAN_HUNDRED = 2
func hasAnyMatch (list: [Int], condition: Int)-> Bool{
var x = false;
switch condition {
case LESS_THAN_TEN :
for a in list {
if a < 10 {
x = true
break
}
}
break
case LESS_THAN_HUNDRED :
for a in list {
if a < 100 {
x = true
break
}
}
break
default:
x = false
}
return x
}
var isLessThanTen = hasAnyMatch([14, 45, 12, 65], condition: LESS_THAN_TEN)
print(isLessThanTen)