1

There was a problem. There are two dictionaries with the same keys. I need to connect them to get the values in half from each dictionary randomly.

Thanks in advance for your answers.

var hiraganaDictionary1 = [
"a":"あ", "i":"い", "u":"う", "e":"え", "o":"お",
"A":"あ", "I":"い", "U":"う", "E":"え", "O":"お",
"ka":"か", "ki":"き", "ku":"く", "ke":"け", "ko":"こ",
"Ka":"か", "Ki":"き", "Ku":"く", "Ke":"け", "Ko":"こ",
"sa":"さ", "shi":"し", "su":"す", "se":"せ", "so":"そ",
"Sa":"さ", "Shi":"し", "Su":"す", "Se":"せ", "So":"そ",
"ta":"た", "chi":"ち", "tsu":"つ", "te":"て", "to":"と",
"Ta":"た", "Chi":"ち", "Tsu":"つ", "Te":"て", "To":"と",
"na":"な", "ni":"に", "nu":"ぬ", "ne":"ね", "no":"の",
"Na":"な", "Ni":"に", "Nu":"ぬ", "Ne":"ね", "No":"の"]


var katakanaDictionary1 = [
"a":"ア", "i":"イ", "u":"ウ", "e":"エ", "o":"オ",
"A":"ア", "I":"イ", "U":"ウ", "E":"エ", "O":"オ",
"ka":"カ", "ki":"キ", "ku":"ク", "ke":"ケ", "ko":"コ",
"Ka":"カ", "Ki":"キ", "Ku":"ク", "Ke":"ケ", "Ko":"コ",
"sa":"サ", "shi":"シ", "su":"ス", "se":"セ", "so":"ソ",
"Sa":"サ", "Shi":"シ", "Su":"ス", "Se":"セ", "So":"ソ",
"ta":"ソ", "chi":"チ", "tsu":"ツ", "te":"テ", "to":"ト",
"Ta":"ソ", "Chi":"チ", "Tsu":"ツ", "Te":"テ", "To":"ト",
"na":"ナ", "ni":"ニ", "nu":"ヌ", "ne":"ネ", "no":"ノ",
"Na":"ナ", "Ni":"ニ", "Nu":"ヌ", "Ne":"ネ", "No":"ノ" ]
  • 1
    Possible duplicate of [Swift: how to combine two Dictionary instances?](https://stackoverflow.com/questions/26728477/swift-how-to-combine-two-dictionary-instances) – えるまる Mar 12 '19 at 12:30

4 Answers4

2
let hiraganaDictionary1 = [
    "a":"あ", "i":"い", "u":"う", "e":"え", "o":"お",
    "A":"あ", "I":"い", "U":"う", "E":"え", "O":"お",
    "ka":"か", "ki":"き", "ku":"く", "ke":"け", "ko":"こ",
    "Ka":"か", "Ki":"き", "Ku":"く", "Ke":"け", "Ko":"こ",
    "sa":"さ", "shi":"し", "su":"す", "se":"せ", "so":"そ",
    "Sa":"さ", "Shi":"し", "Su":"す", "Se":"せ", "So":"そ",
    "ta":"た", "chi":"ち", "tsu":"つ", "te":"て", "to":"と",
    "Ta":"た", "Chi":"ち", "Tsu":"つ", "Te":"て", "To":"と",
    "na":"な", "ni":"に", "nu":"ぬ", "ne":"ね", "no":"の",
    "Na":"な", "Ni":"に", "Nu":"ぬ", "Ne":"ね", "No":"の"]


let katakanaDictionary1 = [
    "a":"ア", "i":"イ", "u":"ウ", "e":"エ", "o":"オ",
    "A":"ア", "I":"イ", "U":"ウ", "E":"エ", "O":"オ",
    "ka":"カ", "ki":"キ", "ku":"ク", "ke":"ケ", "ko":"コ",
    "Ka":"カ", "Ki":"キ", "Ku":"ク", "Ke":"ケ", "Ko":"コ",
    "sa":"サ", "shi":"シ", "su":"ス", "se":"セ", "so":"ソ",
    "Sa":"サ", "Shi":"シ", "Su":"ス", "Se":"セ", "So":"ソ",
    "ta":"ソ", "chi":"チ", "tsu":"ツ", "te":"テ", "to":"ト",
    "Ta":"ソ", "Chi":"チ", "Tsu":"ツ", "Te":"テ", "To":"ト",
    "na":"ナ", "ni":"ニ", "nu":"ヌ", "ne":"ネ", "no":"ノ",
    "Na":"ナ", "Ni":"ニ", "Nu":"ヌ", "Ne":"ネ", "No":"ノ" ]

var mixed = hiraganaDictionary1
for (key, _) in hiraganaDictionary1 {
    if Bool.random() {
        if let value = katakanaDictionary1[key] {
            mixed[key] = value
        }
    }
}
user3441734
  • 16,722
  • 2
  • 40
  • 59
  • It would be better to use [`.merging(…)`](https://developer.apple.com/documentation/swift/dictionary/3127173-merging) method instead of iterating in cycle of just one of dictionaries. – user28434'mstep Mar 12 '19 at 13:00
  • @user28434 done by Rob :-). If for some reason the key doesn't exist in both dictionaries, the value is lost ... and worst, it is lost randomly. – user3441734 Mar 12 '19 at 13:08
  • Ok, when I was writing that comment, Rob Napier's answer was quite different. – user28434'mstep Mar 12 '19 at 13:12
  • 1
    Yeah, I originally misunderstood the question and wrote about merging two half-dictionaries. I had missed the point that the keys were expected to the be the same (I was thinking of two independent sets of keys). – Rob Napier Mar 12 '19 at 13:23
2

Since you want one value for each existing key you can use Bool.random to determine from which dictionary to select the vale

var combined = [String:String]()
hiraganaDictionary1.keys.makeIterator().forEach {
    combined[$0] = Bool.random() ? hiraganaDictionary1[$0] : katakanaDictionary1 [$0]
}

Here is an alternative that for every second turn uses Bool.random() and every other turn uses the opposite of the last call to Bool.random(), this to take 50% from each dictionary

var combined = [String:String]()
var flag = true
var randomFlag: Bool
hiraganaDictionary1.keys.makeIterator().forEach {
    if (!flag) {
        combined[$0] = !randomFlag ? hiraganaDictionary1[$0] : katakanaDictionary1 [$0]
    } else {
        randomFlag =  Bool.random()
        combined[$0] = randomFlag ? hiraganaDictionary1[$0] : katakanaDictionary1 [$0]
    }
    flag = !flag
}
Joakim Danielson
  • 43,251
  • 5
  • 22
  • 52
1

merging(_:uniquingKeysWith:) takes a function that decides how to deal with conflicts. You can use that function to randomly choose between the dictionaries.

let merged = hiraganaDictionary1.merging(katakanaDictionary1,
                                         uniquingKeysWith: { first, second in
                                            Bool.random() ? first : second })
Rob Napier
  • 286,113
  • 34
  • 456
  • 610
0

Bool.random() doesn't guarantee that half the keys would come from each dictionary. As a simple test :

var bool = Bool.random()
var count = 0
for _ in 1...100 {
    if bool { count += 1 }
    bool = Bool.random()
}

print(count)

This could yield 53, 61, 57, ... on multiple runs.

If you want to make sure to get "the values in half from each dictionary randomly", then you could observe that both dictionaries have the same keys, and thus the same count and do :

var mergedDict = [String : String].init(minimumCapacity: hiraganaDictionary1.count)

var bool = Bool.random()

let keys = hiraganaDictionary1.keys.shuffled()

for key in keys {
    mergedDict[key] = bool ? hiraganaDictionary1[key] : katakanaDictionary1[key]
    bool.toggle()
}

Note that the keys have been shuffled before being used. Otherwise, when iterating over them, the keys appear in the same order as they occur in the dictionary’s key-value pairs, which could be biased. Meaning, it could pre-determine which keys, from either dictionary, would appear in the resulting dictionary.

A more efficient way of shuffling the keys would be to shuffle the indices instead:

var mergedDict = [String : String].init(minimumCapacity: hiraganaDictionary1.count)

var bool = Bool.random()

let indices = hiraganaDictionary1.keys.indices.shuffled()

for index in indices {
    let key = hiraganaDictionary1.keys[index]
    mergedDict[key] = bool ? hiraganaDictionary1[key] : katakanaDictionary1[key]
    bool.toggle()
}
ielyamani
  • 17,807
  • 10
  • 55
  • 90