i have two arrays like these
var arr1 = ["han", "Ji", "Kidda", "Ho", "Tusi"]
var arr2 = ["hello", "Ji"]
i want to create a new dictionary that have first element of first array and first element of second array and so on. when the third element of first array comes it should again get the first element of second array.
for example:-
dict = ["han" : "hello", "Ji" : "Ji", "Kidda" : hello, "Ho" : "Ji", "Tusi" : "hello"]
If the second array has 2 items you can do
var dict = [String: String]()
for (index, item) in arr1.enumerated() {
dict[item] = arr2[index % 2]
}
I believe this is what you're looking for (using arr1 as the keys and arr2 as the values repeating them as necessary):
var arr1 = ["han", "Ji", "Kidda", "Ho", "Tusi"]
var arr2 = ["hello", "Ji"]
let dict = Dictionary(uniqueKeysWithValues: zip(arr1, arr1.indices.map { arr2[$0 % arr2.count] }))
print(dict)
["Kidda": "hello", "Ji": "Ji", "han": "hello", "Ho": "Ji", "Tusi": "hello"]
Note:
Dictionaries have no specified ordering. Only the key/value pairings matter. This matches the example in your question.
Explanation:
zip is used to create a sequence of (key, value) tuples from two sequences that will become the key/value pairs for the new Dictionary. The keys come from arr1. map is used to generate the sequence of values from arr2 repeating them as many times as necessary to match the count of arr1. This sequence of (key, value) tuples is passed to Dictionary(uniqueKeysWithValues:) to turn that sequence into the desired Dictionary.
try:
var dict = ["arr1" : "hello", "arr2" : "Ji"]
then for third you can append by
dict[3] = ["arr3" : String(arr3.first())]
Try this:
var arr1 = ["han", "Ji", "Kidda", "Ho", "Tusi"]
var arr2 = ["hello", "Ji"]
var dict : [String : String] = [:]
var arr2Index = 0
for index in 0..<arr1.count {
let arr1Value = arr1[index]
if arr2Index == arr2.count {
arr2Index = 0
}
let arr2Value = arr2[arr2Index]
dict[arr1Value] = arr2Value
arr2Index += 1
}
Here's a fun way:
let arr1 = ["han", "Ji", "Kidda", "Ho", "Tusi"]
let arr2 = ["hello", "Ji"]
let arr3 = Array(repeating: arr2, count: arr1.count).joined()
let d = zip(arr1,arr3).reduce(into: [String:String]()) { $0[$1.0] = $1.1 }
Related
I've two cases where I need to convert strings to different formats.
for ex:
case 1:
string inputs: abc, xyz, mno, & llr // All Strings from a dictionary
output: ["abc","xyz", "mno", "llr"] //I need to get the String array like this.
But when I use this code:
var stringBuilder:[String] = [];
for i in 0..<4 {
stringBuilder.append("abc"); //Appends all four Strings from a Dictionary
}
print(stringBuilder); //Output is 0: abc, 1:xyz like that, how to get desired format of that array like ["abc", "xyz"];
Real usage:
let arr = Array(stringReturn.values);
//print(arr) // Great, it prints ["abc","xyz"];
let context = JSContext()
context?.evaluateScript(stringBuilder)
let testFunction = context?.objectForKeyedSubscript("KK")
let result = testFunction?.call(withArguments:arr); // Here when I debugger enabled array is passed to call() like 0:"abc" 1:"xyz". where as it should be passed as above print.
Secondly how to replace escape chars in swift: I used "\" in replaceOccurances(of:"\\'" with:"'"); but its unchanged. why and how to escape that sequnce.
case 2:
string input: \'abc\'
output: 'abc'
To get all values of your dictionary as an array you can use the values property of the dictionary:
let dictionary: Dictionary<String, Any> = [
"key_a": "value_a",
"key_b": "value_b",
"key_c": "value_c",
"key_d": "value_d",
"key_e": 3
]
let values = Array(dictionary.values)
// values: ["value_a", "value_b", "value_c", "value_d", 3]
With filter you can ignore all values of your dictionary that are not of type String:
let stringValues = values.filter({ $0 is String }) as! [String]
// stringValues: ["value_a", "value_b", "value_c", "value_d"]
With map you can transform the values of stringValues and apply your replacingOccurrences function:
let adjustedValues = stringValues.map({ $0.replacingOccurrences(of: "value_", with: "") })
// adjustedValues: ["a", "b", "c", "d"]
Why not try something like this? For part 1 of the question that is:
var stringReturn: Dictionary = Dictionary<String,Any>()
stringReturn = ["0": "abc","1": "def","2": "ghi"]
print(stringReturn)
var stringBuilder = [String]()
for i in stringReturn {
stringBuilder.append(String(describing: i.value))
}
print(stringBuilder)
Also, part 2 seems to be trivial unless I'm not mistaken
var escaped: String = "\'abc\'"
print(escaped)
case 1:
I have Implemented this solutions, Hope this will solve your problem
let dict: [String: String] = ["0": "Abc", "1": "CDF", "2": "GHJ"]
var array: [String] = []
for (k, v) in dict.enumerated() {
print(k)
print(v.value)
array.append(v.value)
}
print(array)
case 2:
var str = "\'abc\'"
print(str.replacingOccurrences(of: "\'", with: ""))
I am building a project that tells me the unique words in a piece of text.
I have my orginal string scriptTextView which I have added each word into the array scriptEachWordInArray
I would now like to create an array called scriptUniqueWords which only includes words that appear once (in other words are unique) in scriptEachWordInArray
So I'd like my scriptUniqueWords array to equal = ["Silent","Holy"] as a result.
I don't want to create an array without duplicates but an array that has only values that appeared once in the first place.
var scriptTextView = "Silent Night Holy Night"
var scriptEachWordInArray = ["Silent", "night", "Holy", "night"]
var scriptUniqueWords = [String]()
for i in 0..<scriptEachWordInArray.count {
if scriptTextView.components(separatedBy: "\(scriptEachWordInArray[i]) ").count == 1 {
scriptUniqueWords.append(scriptEachWordInArray[i])
print("Unique word \(scriptEachWordInArray[i])")}
}
You can use NSCountedSet
let text = "Silent Night Holy Night"
let words = text.lowercased().components(separatedBy: " ")
let countedSet = NSCountedSet(array: words)
let singleOccurrencies = countedSet.filter { countedSet.count(for: $0) == 1 }.flatMap { $0 as? String }
Now singleOccurrencies contains ["holy", "silent"]
Swift
lets try It.
let array = ["1", "1", "2", "2", "3", "3"]
let unique = Array(Set(array))
// ["1", "2", "3"]
Filtering out unique words without preserving order
As another alternative to NSCountedSet, you could use a dictionary to count the the number of occurrences of each word, and filter out those that only occur once:
let scriptEachWordInArray = ["Silent", "night", "Holy", "night"]
var freqs: [String: Int] = [:]
scriptEachWordInArray.forEach { freqs[$0] = (freqs[$0] ?? 0) + 1 }
let scriptUniqueWords = freqs.flatMap { $0.1 == 1 ? $0.0 : nil }
print(scriptUniqueWords) // ["Holy", "Silent"]
This solution, however (as well as the one using NSCountedSet), will not preserve the order of the original array, since a dictionary as well as NSCountedSet is an unordered collection.
Filtering out unique words while preserving order
If you'd like to preserve the order from the original array (removing element which appear more than once), you could count the frequencies of each word, but store it in a (String, Int) tuple array rather than a dictionary.
Making use of the Collection extension from this Q&A
extension Collection where Iterator.Element: Hashable {
var frequencies: [(Iterator.Element, Int)] {
var seen: [Iterator.Element: Int] = [:]
var frequencies: [(Iterator.Element, Int)] = []
forEach {
if let idx = seen[$0] {
frequencies[idx].1 += 1
}
else {
seen[$0] = frequencies.count
frequencies.append(($0, 1))
}
}
return frequencies
}
}
// or, briefer but worse at showing intent
extension Collection where Iterator.Element: Hashable {
var frequencies: [(Iterator.Element, Int)] {
var seen: [Iterator.Element: Int] = [:]
var frequencies: [(Iterator.Element, Int)] = []
for elem in self {
seen[elem].map { frequencies[$0].1 += 1 } ?? {
seen[elem] = frequencies.count
return frequencies.append((elem, 1))
}()
}
return frequencies
}
}
... you may filter out the unique words of your array (while preserving order) as
let scriptUniqueWords = scriptEachWordInArray.frequencies
.flatMap { $0.1 == 1 ? $0.0 : nil }
print(scriptUniqueWords) // ["Silent", "Holy"]
you can filter the values that are already contained in the array:
let newArray = array.filter { !array.contains($0) }
I tested in Swift 3.0. I want to add array1 to array2, example and errors as below:
var array1: [String?] = ["good", "bad"]
var array2 = [String!]()
array2.append(array1)
//Cannot convert value of type '[String?]' to expected argument type 'String!'
array2.append(contentsOf: array1)
//Extraneous argument label 'contentsOf:'in call
I know if I change to
var array2 = [String?]()
array2.append(contentsOf: array1)
it works!
How should I fix this if i don't change type?
In Swift 3 you cannot define an array where the generic element is an implicitly unwrapped optional.
Implicitly unwrapped optionals are only allowed at top level and as function results.
The compiler
What you can do is creating a new array of String containing only the populated elements of array1.
let array1: [String?] = ["good", "bad", nil]
let array2: [String] = array1.flatMap { $0 }
print(array2) // ["good", "bad"]
Update
As shown by Sam M this is indeed possible, here's the code
let array2 = array1.map { elm -> String! in
let res: String! = elm
return res
}
var array1: [String?] = ["good", "bad"]
var array2 = [String!]()
var array2a = [String]()
for item in array1 {
array2.append(item)
}
for item in array1 {
array2a.append(item!)
}
print("1", array1)
print("2", array2)
print("2a", array2a)
Prints:
1 [Optional("good"), Optional("bad")]
2 [good, bad]
2a ["good", "bad"]
Mapping also works, e.g.:
array2 = array1.map{ $0 }
array2a = array1.filter{ $0 != nil }.map{ $0! }
Let say I have values like this
Apple(100)
Orange(300)
Pineapple(10)
Grape(50)
Banana(1000)
What I want to do is to create an array which was like that to each string
["Apple","100"]
["Orange","300"]
What i tried was like that,but it doesn't meet my answer well enough
var myNewFruits = "Apple(200)"
var newStr = myNewFruits.componentsSeparatedByString("(")
The Output was
["Apple","200)"]
What i really want was
["Apple","200"]
Is there any help with Swift?Thank you.Because I am creating search with that,so,i really need it.
You can use a custom NSCharacterSet and get the first two elements from the returned array:
let myNewFruits = "Apple(200)"
let newStr = myNewFruits.componentsSeparatedByCharactersInSet(NSCharacterSet(charactersInString: "()"))[0...1] // ["Apple", "200"]
You can do it this way:
func stringToArr(str: String) -> [String] {
var newArr = [String]()
var fullNameArr = split(str) {$0 == "("}
newArr.append(fullNameArr[0])
var last: String? = fullNameArr.count > 1 ? fullNameArr[1] : nil
newArr.append(last!.stringByReplacingOccurrencesOfString(")", withString: "", options: NSStringCompareOptions.LiteralSearch, range: nil))
return newArr
}
var string = "Apple(100)" //"Apple(100)"
let newArr = stringToArr(string) //["Apple", "100"]
Is there a cleaner way to get the last two items of an array in Swift? In general, I try to avoid this approach since it's so easy to be off-by-one with the indexes. (Using Swift 1.2 for this example.)
// Swift -- slices are kind of a hassle?
let oneArray = ["uno"]
let twoArray = ["uno", "dos"]
let threeArray = ["uno", "dos", "tres"]
func getLastTwo(array: [String]) -> [String] {
if array.count <= 1 {
return array
} else {
let slice: ArraySlice<String> = array[array.endIndex-2..<array.endIndex]
var lastTwo: Array<String> = Array(slice)
return lastTwo
}
}
getLastTwo(oneArray) // ["uno"]
getLastTwo(twoArray) // ["uno", "dos"]
getLastTwo(threeArray) // ["dos", "tres"]
I was hoping for something closer to Python's convenience.
## Python -- very convenient slices
myList = ["uno", "dos", "tres"]
print myList[-2:] # ["dos", "tres"]
With Swift 5, according to your needs, you may choose one of the following patterns in order to get a new array from the last two elements of an array.
#1. Using Array's suffix(_:)
With Swift, objects that conform to Collection protocol have a suffix(_:) method. Array's suffix(_:) has the following declaration:
func suffix(_ maxLength: Int) -> ArraySlice<Element>
Returns a subsequence, up to the given maximum length, containing the final elements of the collection.
Usage:
let array = [1, 2, 3, 4]
let arraySlice = array.suffix(2)
let newArray = Array(arraySlice)
print(newArray) // prints: [3, 4]
#2. Using Array's subscript(_:)
As an alternative to suffix(_:) method, you may use Array's subscript(_:) subscript:
let array = [1, 2, 3, 4]
let range = array.index(array.endIndex, offsetBy: -2) ..< array.endIndex
//let range = array.index(array.endIndex, offsetBy: -2)... // also works
let arraySlice = array[range]
let newArray = Array(arraySlice)
print(newArray) // prints: [3, 4]
myList[-2:]
Yes, I have an enhancement request filed asking for negative index notation, and I suggest you file one too.
However, you shouldn't make this harder on yourself than you have to. The built-in global suffix function does exactly what you're after:
let oneArray = ["uno"]
let twoArray = ["uno", "dos"]
let threeArray = ["uno", "dos", "tres"]
let arr1 = suffix(oneArray,2) // ["uno"]
let arr2 = suffix(twoArray,2) // ["uno", "dos"]
let arr3 = suffix(threeArray,2) // ["dos", "tres"]
The result is a slice, but you can coerce it to an Array if you need to.
in swift 5 you can use suffix for get objects from the last and use prefix for get objects from the first, here is an example:
let exampleArray = ["first text", "second text", "third text"]
let arr1 = exampleArray.suffix(2) // ["second text", "third text"]
let arr2 = exampleArray.prefix(2) // ["first text", "second text"]
The result is a slice, but you can coerce it to an Array if you need to.
In Swift 2, you can extend CollectionType. Here's an example (borrowing from Rob Napier's answer):
extension CollectionType {
func last(count:Int) -> [Self.Generator.Element] {
let selfCount = self.count as! Int
if selfCount <= count - 1 {
return Array(self)
} else {
return Array(self.reverse()[0...count - 1].reverse())
}
}
}
You can use it on any CollectionType. Here's Array:
let array = ["uno", "dos", "tres"]
print(array.last(2)) // [dos, tres]
Here's CharacterView:
let string = "looking"
print(string.characters.last(4)) // [k, i, n, g]
(Note that my example returns an Array in all cases, not the original collection type.)
More generic answer ...
let a1 = [1,2,3,4,5]
let a2 = ["1","2","3","4","5"]
func getLast<T>(array: [T], count: Int) -> [T] {
if count >= array.count {
return array
}
let first = array.count - count
return Array(array[first..<first+count])
}
getLast(a1, count: 2) // [4, 5]
getLast(a2, count: 3) // ["3", "4", "5"]
the last two items of an array in Swift
EDIT: first checks that myArray.count >= 2
let myArray2:Array? = myArray.count >= 2 ? [myArray[myArray.count-2], myArray[myArray.count-1]] : nil
Here it is wrapped in a function which takes the array and either returns an array containing the last two or else returns nil if the passed array does not contain at least two items.
func getLastTwo(myArray:[String]) -> [String]? {
return myArray.count >= 2 ? [myArray[myArray.count-2], myArray[myArray.count-1]] : nil
}
I doubt it's going to make you that much happier, but the math is certainly simpler:
func getLastTwo(array: [String]) -> [String] {
if array.count <= 1 {
return array
} else {
return array.reverse()[0...1].reverse()
}
}
Note that reverse() is lazy, so this isn't particularly expensive.
let items = [0, 2, 5, 3, 7, 6, 9, 10]
let count = items.count
let last2 = items[count - 2 ..< count] // [9, 10]
Swift4 solution:
let oneArray = ["uno"]
let twoArray = ["uno", "dos"]
let threeArray = ["uno", "dos", "tres"]
let arr1 = threeArray.suffix(from: threeArray.count-2) // ["dos", "tres"]
Other examples to clarify the functionality of Swift's built in function func suffix(from start: Int) -> ArraySlice<Element> are...
let arr2 = oneArray.suffix(from: 0) // ["uno"]
let arr3 = twoArray.suffix(from: 0) // ["uno", "dos"]
let arr4 = twoArray.suffix(from: 1) // ["dos"]
let arr5 = threeArray.suffix(from: 1) // ["dos", "tres"]
let arr6 = threeArray.suffix(from: 2) // ["tres"]