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

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

ただいまの
回答率

90.60%

  • Swift

    7039questions

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

  • Swift 2

    1331questions

    Swift 2は、Apple社が独自に開発を行っている言語「Swift」のアップグレード版です。iOSやOS X、さらにLinuxにも対応可能です。また、throws-catchベースのエラーハンドリングが追加されています。

テキストベースの辞書から変換する方法がわからない

解決済

回答 3

投稿 編集

  • 評価
  • クリップ 1
  • VIEW 748

Nicola

score 15

以下のようなテキストファイルから、ひらがなの入力文字から、特定の行を選択していくいい方法がありませんか?
テキストではなく、データベース化しないとダメでしょうか?

辞書の一部です。
あいしてます    829    231    6826    あいしてます
あいすてーしょん    1866    1773    8007    愛ステーション
あいすと    1773    262    5711    アイスと
あいすと    1773    359    6287    アイスと
あいすと    1773    375    6655    アイスと
あいそれ    1773    1829    7426    あいそれ


よろしくお願いします。
  • 気になる質問をクリップする

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

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

    クリップを取り消します

  • 良い質問の評価を上げる

    以下のような質問は評価を上げましょう

    • 質問内容が明確
    • 自分も答えを知りたい
    • 質問者以外のユーザにも役立つ

    評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

    質問の評価を上げたことを取り消します

  • 評価を下げられる数の上限に達しました

    評価を下げることができません

    • 1日5回まで評価を下げられます
    • 1日に1ユーザに対して2回まで評価を下げられます

    質問の評価を下げる

    teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。

    • プログラミングに関係のない質問
    • やってほしいことだけを記載した丸投げの質問
    • 問題・課題が含まれていない質問
    • 意図的に内容が抹消された質問
    • 広告と受け取られるような投稿

    評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。

    質問の評価を下げたことを取り消します

    この機能は開放されていません

    評価を下げる条件を満たしてません

    評価を下げる理由を選択してください

    詳細な説明はこちら

    上記に当てはまらず、質問内容が明確になっていない質問には「情報の追加・修正依頼」機能からコメントをしてください。

    質問の評価を下げる機能の利用条件

    この機能を利用するためには、以下の事項を行う必要があります。

回答 3

checkベストアンサー

+2

タブ区切りテキストのようですから、CSVをパースする要領で配列に変換することはできます。
let data = NSString(contentsOfFile: "/path/to/data.txt", encoding: NSUTF8StringEncoding, error: nil) as String
data.enumerateLines { (line, stop) -> () in
    println(line)
    println(split(line,{ $0 == "\t"}))
}
ただし、これではメモリに常駐させる必要がある上、検索なども自分で実装する必要があります。
(検索効率を考えて、配列以外のデータに格納するなど)

単純にテキストを検索するなどの方法を採りたいのであれば、
テキストをデータベースに格納して、
データベースにすでにある機能を活用するのが一番の近道だと思います。

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2015/07/29 11:57

    1ファイル8M以上のファイル×10個になります。やはり、動作やメモリーを考えたら、データベース化するのが現実的でしょうか?

    キャンセル

  • 2015/07/29 12:45

    メモリーのことはもちろんですが、検索などもデータベースのクエリを使った方が高速かつ効率的でしょう。
    データベースを使えば、インデックスの張り方やクエリの書き方次第で高速化や効率化は可能です。
    自前で検索のアルゴリズムを実装するのは、勉強にはなってもあまり現実的とはいえません。(うまくすればデータベースよりも高速に動作させられそうですが)

    キャンセル

  • 2015/07/31 09:22

    サンプルコードまでありがとうございます。
    しかし、"/path/to/data.txt"のところがエラーで使えませんでした。
    初心者なもので、このエラーの解決に未だ時間が割かれています•••
    String in not convertible to 'StringLiteralConvertible'
    はたして?
    すみません。

    キャンセル

  • 2015/07/31 09:46

    contentsOfFileで渡しているパスは正しく読み込むファイルを指していますか?
    読み込むファイルのエンコードはあっていますか?
    上記2点を確認してみてください。

    ファイルのパスは、配置するところで変わってしまうので、NSSearchPathForDirectoriesInDomains等で検索してセットする方が良いかもしれません。
    読みこみファイルのエンコードは、サンプルではUTF8なので、違っている場合はそれ合わせて変更してください。

    キャンセル

  • 2015/07/31 09:56

    データベースを使用するのであれば、
    事前にSQLite等のデータベースファイルを作成してしまって、
    それをアプリでインポートする方が、
    iOSアプリ内でテキストを読み込んでDBに格納するよりも手軽にすむかと思います。
    (データ更新方法によっては、アプリ内でDBに格納する方が良いときもありますが)

    タブ区切りテキストをSQLiteデータベースに変換する方法はここが参考になるかと。
    http://www.dbonline.jp/sqlite/manage/index2.html

    キャンセル

  • 2015/07/31 16:19

    色々調べた結果、以下のソースになっていますが、正しく動作しません。

    let documentsPath = NSSearchPathForDirectoriesInDomains(.DocumentDirectory, .UserDomainMask, true)[0] as String
    let fileName = "dictionary00.txt"
    let data = NSString(contentsOfFile: "\(documentsPath)+\(fileName)" , encoding: NSUTF8StringEncoding, error: nil)

    で、3行目でViewController.Type dose not have a member named documentsPathエラーになってしまいます。
    ファイルも形式もあっているはずです。

    お忙しいところすみませんが、アドバイスいただけないでしょうか。
    よろしくお願いいたします。

    キャンセル

  • 2015/07/31 16:32

    https://realm.io/jp/ というものを試しています。
    SQLiteの方がいいのでしょうか?

    キャンセル

  • 2015/07/31 16:55

    swiftあんまり得意じゃないので自信が無いですが
    エラーとしては、documentsPathが認識できないようなエラーのようですが。

    let paths = NSSearchPathForDirectoriesInDomains(.DocumentDirectory,
    .UserDomainMask, true)
    let filePath = paths[0].stringByAppendingPathComponent("dictionary00.txt")
    let data = NSString(contentsOfFile: filePath, encoding: NSUTF8StringEncoding, error: nil)
    で行けませんか?

    キャンセル

  • 2015/07/31 16:58

    realmは最近出てきたやつで、SQLiteよりもずっと良いようです。
    残念ながら私は使う機会が無くて、まだ勉強していませんが、新しく学ぶのならそちらの方がいいと思います。

    キャンセル

+1

回答が遅くなりましたが、たとえばこんな方法で。
流れとしては、辞書検索は外部のコマンドに任せ、swift側では結果だけを取得して後続処理をするという感じです。

【準備1】awk を使った辞書検索
①辞書を適当なディレクトリ配下に配置します。たとえば以下のように複数ファイルに分かれて存在するとして、

/usr/local/dic/dic_{連番}.txt

たとえば以下のような感じで。

===[ /usr/local/dic/dic_01.txt ]===========
あいしてます    829    231    6826    あいしてます
あいすてーしょん    1866    1773    8007    愛ステーション
あいすと    1773    262    5711    アイスと
あいすと    1773    359    6287    アイスと

===[ /usr/local/dic/dic_02.txt ]===========
あいすと    1773    375    6655    アイスと
あいそれ    1773    1829    7426    あいそれ
こうしておくと、awk のワンライナーで以下のように検索できます。
(キーワードの完全一致でも検索できますが、下記の例では前方一致の例を示してあります)

$ /usr/local/bin/gawk -F'\t' -v k='^あいす' '$1 ~ k' /usr/local/dic/dic_*.txt
あいすてーしょん    1866    1773    8007    愛ステーション
あいすと    1773    262    5711    アイスと
あいすと    1773    359    6287    アイスと
あいすと    1773    375    6655    アイスと
$

$ /usr/local/bin/gawk -F'\t' -v k='^あいすて' '$1 ~ k' /usr/local/dic/dic_*.txt
あいすてーしょん    1866    1773    8007    愛ステーション
$
この方式だと、辞書ファイル(テキストファイル)が後からいくつ追加されてもOKです。

【準備2】swift から呼び出しやすいようにスクリプト化
swift側の記述が楽なように、awkのワンライナーをスクリプト化しておきます。
忘れずに実行権を付けておいてください。

/usr/local/dic/search_dic.sh

#!/bin/bash
/usr/local/bin/gawk -F'\t' -v k="^$1" '$1 ~ k' /usr/local/dic/dic_*.txt

【swiftからの呼び出し】
いよいよ、swift側から呼び出します。

import Foundation

var keyword : String = "あいすと"
var cmd : String = "/usr/local/dic/search_dic.sh"

var task:NSTask = NSTask()
task.launchPath = cmd
task.arguments  = [keyword]
var pipe:NSPipe = NSPipe()
task.standardOutput = pipe
task.launch()
var output:NSData = pipe.fileHandleForReading.readDataToEndOfFile()
var outputStr:NSString = NSString(data:output,encoding:NSUTF8StringEncoding)!

println(outputStr)

そうすると、コマンドラインでのスクリプト実行結果が文字列として取得されます。

あいすと    1773    262    5711    アイスと
あいすと    1773    359    6287    アイスと
あいすと    1773    375    6655    アイスと

あとは処理したい内容に応じて、取得した結果(文字列)を配列に突っ込むなどして、好きなように料理してください。

ただし、こうして得られた「結果」を、他のスレッドでご質問のようにiOSで運用しようとお考えならば、素直にモバイル向けのDBをご使用になられた方が楽ですね。。。
最近では Realm が注目されているようですが。

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

0

タブ区切りのテキストファイル(TSV)から特定の文字列で検索したいだけなら、awkコマンドのワンライナーで簡単かつ高速に検索することが出来ます。
データをメモリーに常駐させる必要もありませんし、何も考えずにDB化する位なら遜色のない速度で検索可能です。

DB化すべきかどうかは、むしろ検索結果をどの様に利用するか、そして今後データをどの様にメンテナンスして行くかによって決まって来ます。

MySQLのようなRDBSを利用するメリットは
①ロック機構による排他制御がし易い
②トランザクション制御がし易い
③テーブルを正規化し、制約やリレーションを定義しておけば、データの整合性を担保し易い
などです。

データのreadとwriteのプロセスが同時に処理される可能性があるとか、ひとまとまりの処理が完全に成功した場合のみデータを更新したいとか、データ項目間に何らかの関連や制約があって整合性を保ったまま更新するためにデータの検査が必要ならば是非ともDB化してください。

一方、単純に行単位のデータ追加があるだけの辞書から、手際良く該当の行を選択したいだけならば、awkのワンライナーがオススメです。
結構複雑な検索条件にも簡単に対応できます。

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2015/07/30 13:06

    Googleさんで調べてみているんですが、AWKコマンドはあまり情報がありません(調べ方が悪いのか?)
    SwiftでiOSソフトの中に組み込んで使えるんですか?
    見つけたのが、コマンドラインでの使用法だったので…

    やっぱり、DBなんでしょうか?

    キャンセル

  • 2015/08/01 17:36

    「SwiftでiOSソフトの中に組み込んで使えるんですか?」
    ⇒ 使えますよ!ちょっと長くなるので、別途参考情報を回答します。

    キャンセル

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

  • ただいまの回答率 90.60%
  • 質問をまとめることで、思考を整理して素早く解決
  • テンプレート機能で、簡単に質問をまとめられる

関連した質問

同じタグがついた質問を見る

  • Swift

    7039questions

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

  • Swift 2

    1331questions

    Swift 2は、Apple社が独自に開発を行っている言語「Swift」のアップグレード版です。iOSやOS X、さらにLinuxにも対応可能です。また、throws-catchベースのエラーハンドリングが追加されています。