質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.35%
iOS

iOSとは、Apple製のスマートフォンであるiPhoneやタブレット端末のiPadに搭載しているオペレーションシステム(OS)です。その他にもiPod touch・Apple TVにも搭載されています。

Swift

Swiftは、アップルのiOSおよびOS Xのためのプログラミング言語で、Objective-CやObjective-C++と共存することが意図されています

Q&A

解決済

2回答

645閲覧

配列を含む構造体配列と、別の配列を比較して一致したものがあるかないかを高階関数で判定したい

tobenai_buta

総合スコア13

iOS

iOSとは、Apple製のスマートフォンであるiPhoneやタブレット端末のiPadに搭載しているオペレーションシステム(OS)です。その他にもiPod touch・Apple TVにも搭載されています。

Swift

Swiftは、アップルのiOSおよびOS Xのためのプログラミング言語で、Objective-CやObjective-C++と共存することが意図されています

0グッド

0クリップ

投稿2021/05/10 00:02

編集2021/05/10 04:35

やりたいこと

配列を含む構造体配列と、別の配列を比較して一致したものがあるかないかを判定したいです。
下のようにデータが入っており receipts の値が menus の各 Price に含まれるかを高階関数で書いた場合どう書くかが知りたいです。

宣言部

struct Menu { public let name: String public let text: String public let price: [Price] } struct Price { public let size: String public let yen: Int } struct Receipt { public let yen: Int }

データはこんな感じで入っています

let menus:[Menu] = [Menu(name: "牛丼", text: "牛肉が乗ってます", price: [Price(size:"並盛", yen:380),Price(size:"大盛", yen:430),Price(size:"特盛", yen:560)]), Menu(name: "豚丼", text: "豚肉が乗ってます", price: [Price(size:"並盛", yen:390),Price(size:"大盛", yen:440),Price(size:"特盛", yen:570)]), Menu(name: "カルビ丼", text: "カルビが乗ってます", price: [Price(size:"並盛", yen:400),Price(size:"大盛", yen:450),Price(size:"特盛", yen:580)])] let receipts:[Receipt] = [Receipt(yen:320),Receipt(yen:590),Receipt(yen:620),Receipt(yen:400)]

ループ文で回した場合の処理

var result = false menus.forEach{ menu in menu.price.forEach{ price in receipts.forEach{ receipt in if( price.yen == receipt.yen ){ result = true } } } } return result

実行結果

///Receipt(yen:400)とカルビ丼の400が同じ値なのでtrue true

補足情報(FW/ツールのバージョンなど)

XCode10
Swift4

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

hoshi-takanori

2021/05/10 01:32

forEach には戻り値はないので、エラーになりますよね…。 とりあえず contains(where:) を使えば良いのでは。
tobenai_buta

2021/05/10 04:35

たしかに、失礼しました。 修正しました。
guest

回答2

0

forEachも高階関数の1つですし、hoshi-takanoriさんがアドバイスされているcontainsも高階関数の1つです。
containsを使って、次のように処理するのが適切だと思います。

swift

1let result = menus.contains { menu in 2 menu.price.contains { price in 3 receipts.contains { receipt in 4 receipt.yen == price.yen 5 } 6 } 7}

filterを使って配列を絞り込み、要素が残っている場合をtrueにしたいのであれば、

swift

1let result = menus.filter { menu in 2 menu.price.filter { price in 3 receipts.filter { receipt in 4 receipt.yen == price.yen 5 }.count > 0 6 }.count > 0 7}.count > 0

このように書くこともできると思いますが、要素が含まれているか否かを判定したいだけなら、containsを使った方が、条件を満たす要素を見つけた時に残りの要素を処理しないので効率的だと思います。

投稿2021/05/10 05:25

TakeOne

総合スコア6299

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

tobenai_buta

2021/05/11 07:05

ありがとうございます! containsやfilterを使って書く場合もforEachと基本的にあまり変わらないんですね。
guest

0

ベストアンサー

こうとかですか?

swift

1let result = receipts.map(.yen).contains(where: Set(menus.flatMap(.price).map(.yen)).contains) 2)

投稿2021/05/10 10:28

MasakiHori

総合スコア3391

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

tobenai_buta

2021/05/11 07:15

ありがとうございます! 一回flatMapで一つの配列にして、そこからcontainsで比較すればいいんですね。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.35%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問