マンガでよめる痔のこと・薬のこと

 お世話になっております。
 少し無謀な質問かもしれませんが・・・。
dim s1 as string, s2 as string
dim v as double
s1 = "abcde"
s2 = "cd"
という条件の時、
v = aimai(s1, s2)
とすれば、vに0.4だとか0.2だとか、「s1とs2がどのくらい似ているか」を返す関数、もしくはアルゴリズムは存在するのでしょうか。
 返り値の最大値は1.0(完全一致)、最小値は0(何一つ同じ文字がなかった)となるとします。

 何を以て「似ている」と評価するかですが、
・何文字含まれるか
・並び順
という要素は、重要でしょうね。

 s2を1文字ずつ分解し、正規表現でヒットするかという流れ
/*
 初めは、.+c.+
 次は、.+cd.+、それと.+c.*d.+
*/
を考えたのですが、私には一般化できそうにありません。

このQ&Aに関連する最新のQ&A

A 回答 (2件)

★『あいまい評価関数』は標準ではないと思います。


・特に完全一致のときが『1.0』で不一致が『0.0』で、数箇所の文字が一致すると小数で返す関数は
 自分で実装するしかないでしょう。
・アルゴリズムは、上記の仕様を元に考えれば出来そうですね。
 つまり、完全一致した場合は『1.0』を返して数箇所の文字(文字列)が一致した場合は、文字列の
 長さと一致した個数からパーセントを算出します。このパーセントを小数に変換して返せば良いでしょう。
・また、一致する文字(文字列)が1つもなければ『0.0』を返すようにします。
・簡単なアルゴリズムでは、文字列『s1』の中に文字列『s2』が何箇所、含まれるかカウントします。
 ゼロの場合は、『s2』を文字単位に分解して文字列『s1』から何箇所、含まれるかカウントします。
 文字単位でどれも含まれなければ『0.0』を返す。
・上記のアルゴリズムで含まれる文字列の個数や文字単位の個数を使って、文字列『s1』の文字数との
 パーセントを算出します。算出方法は例えば、
 s1=abcdefcd123(11バイト)
 s2=cd(2バイト)
 の場合『cd』が2箇所一致します。そこで『s2の長さ』×『2箇所一致』÷『s1の長さ』=4÷11=0.3636…
 を戻り値に返せばいいでしょう。
・以上。おわり。→アルゴリズムの参考にして下さい。
    • good
    • 0
この回答へのお礼

 ご回答、ありがとうございます。
 その後いろいろと考えたのですが、私が考えている事柄については、「沖田十三」という文字列に対して、「沖田十四」より「沖田十三(ヤマト初代艦長)」の方が、高い一致度を返して欲しいみたいです。
 となると、数値で返すという基本方針に、かなりの無理がありますね。

 再度、基本から見直してみます。

お礼日時:2007/02/15 11:31

VBの関数は数も少ないのでVBの本や解説WEBを見ればすぐ判る。

質問しなくても判る。本やWEBを見なくても、その内容の盛り沢山さから、関数としては採用されてないことは判る。自分でそれ向けのプログラムを作るよりほかない。
>もしくはアルゴリズムは存在するのでしょうか。
これもプログラムを作成する人が考えることです。アルゴリズム事典でも載っているなら、あるといえるでしょう。
プログラマが採用したロジックをすべてアルゴリズムというのはおこがましいと思う。
本件はそう壮大な(データが多い、処理計算が膨大に多いので工夫がいるなど)内容ではないので、アルゴリズムというほどのすっきりした解法の問題ではないでしょう。
質問者自身で(下記で)それを語っているではないですか。
>返り値の最大値は1.0(完全一致)、最小値は0(何一つ同じ文字がなかった)となるとします。
 何を以て「似ている」と評価するかですが、
・何文字含まれるか
・並び順
ーー
文字の場合は機械的にそれで(上記で)よいでしょう。しかしその記号が現実世界の事象を抽象化したものなら、有無しのほか、距離とか近縁、質量(引力の源)などの定義を持ち込む人がいるかもしれない。ですからその辺は、プログラマに聞くより、理数系の方がみるカテゴリを選んで質問しなおしては。
人もの金の世界のプログラムを扱う方が文系プログラマには多く、質問のようなことを考える必要はほぼないと思うから。
正規表現が役立つかどうかも、文字列の有無の問題で、問いかけ法の集約にしか過ぎず、それ以上の一般化のプログラムテクニックの問題には使えないと思う。
VB使いに聞くべき以上の質問だといいたい。したがってOKWAVEでは現状カテ不適当。
それと実際は何の世界のことを考えた挙句なのか、やはり明示して質問すべきでは。それを回答者がわきまえないで回答すると、回答者はやけどする。Fazzy理論でも考えているお仲間に質問したら。
それに大学や大学院で議論する問題ではないかと思うが、それらをこのカテで質問されるのもどうかと思います。
    • good
    • 0
この回答へのお礼

 ご意見、ありがとうございます。

お礼日時:2007/02/15 11:32

このQ&Aに関連する人気のQ&A

お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!

このQ&Aを見た人はこんなQ&Aも見ています

このQ&Aを見た人が検索しているワード

このQ&Aと関連する良く見られている質問

QExcel 文字列 一致

2つの文字を比較して一致した文字の数を数える関数があれば教えてください。

例えばExcelでA1セルに「海山商事」A2セルに「海猫商事」を入れて比較し、一致している文字数(この場合は「3」)をA3に出力したいのですがどうしたらよいですか?大変恐縮ですがアドバイスください。よろしくお願いします。

Aベストアンサー

=SUMPRODUCT(ISNUMBER(FIND(MID(B1,ROW(INDIRECT("1:"&LEN(B1))),1),A1))*1)

※注意
「海山商事」と「山海商事」だと4が結果になります。

Q■近似している文字列を抽出したい

エクセル内に数万件のレコードが書き込まれています。
登録されているデータの品質をチェックしたいため、
特定の列を参照し、類似しているデータは一括で抽出したいと考えています。

エクセルの関数だけに限った際、
下記のようなやり方があるかと思いますが、
一括で抽出することができないためお知恵をいただきたい所存です。

現在のチェック方法
(1)B2のリンゴをA1にコピーし、C列はA1とB列の文字列の適合率を表示する。
(2)C列の適合率が高いもの(仮に90%以上適合した文字列)を目検でチェック
(3)B3以降をA1に順次コピーして(1)~(2)のチェックを行う
      |A列   |B列   |C列
1     |リンゴ |       |
2     |     |リンゴ   |100%
3     |     |すいか  |0%
4     |     |もも    |0%
5     |     |すもも   |0%
6     |     |メロン   |33%
7     |     |生ハム  |0%
8     |     |おリンゴ |100%


■ご質問させていただく内容
・近似した文字列の適合率を一括で調べるもしくは抽出するツールをご存知でしょうか?
・もしくは、上記に記載した内容をマクロで組むことができるでしょうか?
例えば以下のような流れです。
※上図を参考に説明
(1)Sheet1のB2の文字列の適合率をB2:B8まで順次計算してC列に代入
(2)Sheet1のC列を参照し、B2の行以外で適合率が90%以上の場合、Sheet2のA列に代入
(3)B3~B8まで(1)~(2)の処理を繰り替えす。
※参考になるサイトやプログラムなどをご教示いただければ幸いです。

よろしくお願い致します。

エクセル内に数万件のレコードが書き込まれています。
登録されているデータの品質をチェックしたいため、
特定の列を参照し、類似しているデータは一括で抽出したいと考えています。

エクセルの関数だけに限った際、
下記のようなやり方があるかと思いますが、
一括で抽出することができないためお知恵をいただきたい所存です。

現在のチェック方法
(1)B2のリンゴをA1にコピーし、C列はA1とB列の文字列の適合率を表示する。
(2)C列の適合率が高いもの(仮に90%以上適合した文字列)を目検でチェック
(3)B3以降...続きを読む

Aベストアンサー

こんばんは!
ExcelでVBAの一例です。

↓の画像で左側がSheet1・右側がSheet2とします。

Alt+F11キー → メニュー → 挿入 → 標準モジュール → VBE画面に
↓のコードをコピー&ペーストしてマクロを実行してみてください。
(Alt+F8キー → マクロ → マクロ実行です)

Sub Sample1() 'この行から
Dim i As Long, j As Long, k As Long, cnt As Long, str As String, wS1 As Worksheet, wS2 As Worksheet
Set wS1 = Worksheets("Sheet1")
Set wS2 = Worksheets("Sheet2")
i = wS2.Cells(Rows.Count, "A").End(xlUp).Row
If i > 1 Then
Range(wS2.Cells(2, "A"), wS2.Cells(i, "C")).ClearContents
End If
wS2.Range("B:B").Style = "Percent" '←Sheet2のB列を%表示にしている場合は不要
With wS1
For i = 2 To .Cells(Rows.Count, "B").End(xlUp).Row
.Range("A1") = .Cells(i, "B")
For j = 2 To .Cells(Rows.Count, "B").End(xlUp).Row
If InStr(.Cells(j, "B"), .Range("A1")) > 0 Then
.Cells(j, "C") = 1
Else
For k = 1 To Len(.Range("A1"))
str = Mid(.Range("A1"), k, 1)
If InStr(.Cells(j, "B"), str) > 0 Then
cnt = cnt + 1
End If
Next k
.Cells(j, "C") = cnt / Len(.Range("A1"))
cnt = 0
End If
If .Range("A1") <> .Cells(j, "B") And .Cells(j, "C") >= 0.9 Then
With wS2.Cells(Rows.Count, "A").End(xlUp).Offset(1)
.Value = wS1.Cells(j, "B")
.Offset(, 1) = wS1.Cells(j, "C")
.Offset(, 2) = wS1.Range("A1")
End With
End If
Next j
Next i
.Range("C:C").ClearContents
End With
End Sub 'この行まで

※ 余計なお世話かもしれませんが、Sheet2のC列にはSheet1のA1セルのデータの場合で
B列にはそれに対する割合を表示させています。
Sheet2の2行目を説明すると
A1セルが「リンゴ」の時に「おリンゴ」が100%になります

同様に3行目はSheet1のA1セルが「もも」の時に「すもも」が100%
というコトになります。
(Sheet1のC列データは最終的には消しています)

外していたらごめんなさいね。m(_ _)m

こんばんは!
ExcelでVBAの一例です。

↓の画像で左側がSheet1・右側がSheet2とします。

Alt+F11キー → メニュー → 挿入 → 標準モジュール → VBE画面に
↓のコードをコピー&ペーストしてマクロを実行してみてください。
(Alt+F8キー → マクロ → マクロ実行です)

Sub Sample1() 'この行から
Dim i As Long, j As Long, k As Long, cnt As Long, str As String, wS1 As Worksheet, wS2 As Worksheet
Set wS1 = Worksheets("Sheet1")
Set wS2 = Worksheets("Sheet2")
i = wS2.Ce...続きを読む

QaccessかExcelで類似検索はできますか?

accessかExcelで類似検索はできますか?

accessで単語の類似検索はできますか?
たとえば、「パイナップル」と「ハイナップル」のように一文字だけ違う単語とか
「パイナップル!」のように特定の文字列が付加されている単語を検索したいのです。
VBAを使ったやり方でもよいので教えていただけないでしょうか。

Aベストアンサー

文字列の類似度を表すレーベンシュタイン距離というのをAccessのクエリで使ってみた事があります。
「パイナップル」と「ハイナップル」なら1になりますので、ユーザー定義式の結果が1になるレコードを抽出といった形で使えます。一文字だけの相違ならすっきりとした結果が出ますが、何文字か異なっていると、なかなか思った通りにはいかなかった記憶があります。
レーベンシュタイン距離 VBAで、下記がヒットしましたので、ご参考に載せておきます。
http://pub.ne.jp/arihagne/?entry_id=2781916

QEXCEL VBA で現在開いているブックのファイル名を取得する方法

EXCEL2003 VBAで業務を簡素化するために、現在開いているブックのファイル名を取得する方法が分かりません。
作業手順をマクロを使って処理していますが、オリジナルのワークブックをファイル名を変えて保存し、以後、このワークブックを読み込んで使用しています。
このときのVBAは、オリジナルのファイル名を使っているため、ファイル名を変更するとエラーになり、以後の業務に使用できません。
常にファイル名を取得出来るVBAをどなたか、教えて下さい。

Aベストアンサー

>現在開いているブックのファイル名
 ちょっと曖昧な表現かなぁという気もいたしますが、VBAが書いてあるブックのブック名は
ThisWorkbook.Name
で、現在 "アクティブにして" 操作対象になっているブックの名前は
ActiveWorkbook.Name
ですね。

 しかし、
>VBAは、オリジナルのファイル名を使っているため、ファイル名を変更するとエラーになり
というような文脈からすると、
ThisWorkbook.Name
の方ですかね。

QVB上で実行中の無限ループの止め方

今まで、CUIベースのBASICでのプログラムの経験はあるのですが
Visual系のBASICは初心者です。
原因はわかっているのでプログラムの修正はできるのですが
VB上でコンパイルして実行したときに無限ループに陥ってしまって
どうにもプログラムをとめられなくなります。
そんなことがないように、実行前に全てのプロジェクトを保存して
いますので、そんなに実害はないのですが、どうすればとめられるのでしょう・・
今現在は、タスクマネージャーから強制終了させています。

Aベストアンサー

無限ループの一番内側に
DoEvents
を入れておくと、ウィンドウ切替え->デバッガ終了操作が出来ますよ

危なそうなとこにも入れておくと、何かと安心です。

QEXCEL VBAで計算値を四捨五入、切り上げ、切捨てする方法

ネットで探してみたのですが、計算結果を四捨五入して特定のセルを
返すにはどうしたらいいのでしょうか?

Sub hokangosa()

Dim ZPS As Double
Dim ZPOS As Double
Dim DMN As Double
MsgBox (" >>> 補間誤差自動計算 <<< ")
MsgBox (" >>> 初期値入力します <<< ")
ZPS = InputBox(">>> ステップを入力してください<<<")
ZPOS = Sheet1.Cells(22, 4).Value
DMN = ZPOS / ZPS
Sheet1.Cells(23, 6).Value = DMN
End Sub

ここでDMNの値を四捨五入したいです。

またこれとは別に切上げ、切捨ても教えていただけるとありがたいです。

Aベストアンサー

DMN = Application.WorksheetFunction.Round(ZPOS / ZPS, 0)
で、四捨五入
DMN = Application.RoundDown(ZPOS / ZPS, 0)
で切り捨て
DMN = Application.RoundUp(ZPOS / ZPS, 0)
で切り上げです。

引数で、対象桁を変更できます。

QVBA オブジェクトが空かどうか判定する

皆様のお知恵を拝借させてください。

エクセルVBAでオブジェクトを入れる変数を定義し、その変数にオブジェクト
が入っているかどうか検査したいのですがどうしたらいいでしょうか。

例えば---
Dim a As Workbook
If a <> nothing then ←この部分が分からない。このままだとエラー。
処理
End if
---------
環境
エクセル2003
WinXPsp1

Aベストアンサー

もし、aが空だったら
If a Is Nothing Then 

もし、aが空じゃなかったら
If Not a Is Nothing Then

QエクセルVBAのフォームを最前面にする方法を教えてください。

エクセルVBAなのですが、UserForm1を最前面に表示して、
他のどのウインドウをアクティブにしても消えない状態にしたいのですが、
どのようなコードを書けばできるでしょうか。
VB.NETで表すとMe.TopMost = Trueとなると思うのですが、
エクセルVBAだとそのような書き方はないようです。

もうしわけございませんがご教示頂きたく、お願いいたします。m(__)m

Aベストアンサー

あらかじめ、フォームのプロパティの[ShowModal]をFalseにしておいて、以下のような方法ではダメでしょうか?
画面のアクティブイベントを利用するのは、個人的に嫌いなのですが。。。


Private Declare Function GetForegroundWindow Lib "user32" () As Long
Private Declare Function SetWindowPos Lib "user32" (ByVal hwnd As Long, ByVal hWndInsertAfter As Long, ByVal x As Long, ByVal y As Long, ByVal cx As Long, ByVal cy As Long, ByVal wFlags As Long) As Long
Private Const HWND_TOPMOST As Long = -1
Private Const SWP_NOSIZE As Long = &H1&
Private Const SWP_NOMOVE As Long = &H2&


Private Sub UserForm_Activate()
Call SetWindowPos(GetForegroundWindow, HWND_TOPMOST, 0, 0, 0, 0, SWP_NOMOVE Or SWP_NOSIZE)
End Sub

あらかじめ、フォームのプロパティの[ShowModal]をFalseにしておいて、以下のような方法ではダメでしょうか?
画面のアクティブイベントを利用するのは、個人的に嫌いなのですが。。。


Private Declare Function GetForegroundWindow Lib "user32" () As Long
Private Declare Function SetWindowPos Lib "user32" (ByVal hwnd As Long, ByVal hWndInsertAfter As Long, ByVal x As Long, ByVal y As Long, ByVal cx As Long, ByVal cy As Long, ByVal wFlags As Long) As Long
Private Const HWND_TOPMOS...続きを読む

QVB.NET2005 DataGridViewでレコードを絞り込んで表示

Form1のTextboxより入力した数字を元にForm2のload時にoracleDBをselectしDataGridviewのテーブルの中に作成した値と一致するものを絞り込んで表示したいと考えております。
メニューのプロジェクトからDataSetを選択し、必要なDBを選択しTableadapter等も利用しています。
DBから読み込んだものをそのまま表示するだけという事は出来ました。
テキストやネットを調べながら色々試してみましたが、うまくいかず煮詰まっています。
お力を貸してください。よろしくお願いします。

Aベストアンサー

お世話になります。

TableAdapter から取ってきた DataTable を元に
DataView を使って絞り込めばよいのでは?

Dim dt As DataTable = New DataTable
dt.Columns.Add("ID", GetType(Integer))
dt.Columns.Add("FRUIT", GetType(String))

dt.Rows.Add(New Object() {1, "りんご"})
dt.Rows.Add(New Object() {2, "もも"})
dt.Rows.Add(New Object() {3, "かき"})
dt.Rows.Add(New Object() {4, "みかん"})

Dim dv As DataView = New DataView(dt)
dv.RowFilter = "FRUIT LIKE '%ん%'" '絞り込み

Me.DataGridView1.DataSource = dt '全件
Me.DataGridView2.DataSource = dv '絞り込まれた結果(りんごとみかん)

参考URL:http://www.atmarkit.co.jp/fdotnet/dotnettips/129dgfilter/dgfilter.html

お世話になります。

TableAdapter から取ってきた DataTable を元に
DataView を使って絞り込めばよいのでは?

Dim dt As DataTable = New DataTable
dt.Columns.Add("ID", GetType(Integer))
dt.Columns.Add("FRUIT", GetType(String))

dt.Rows.Add(New Object() {1, "りんご"})
dt.Rows.Add(New Object() {2, "もも"})
dt.Rows.Add(New Object() {3, "かき"})
dt.Rows.Add(New Object() {4, "みかん"})

Dim dv As DataView = New DataView(dt)
dv.RowFilter = "FRUIT LIKE '%ん%'" '絞り込み...続きを読む

Qvlookup関数で検索値を含む文字列を検索する方法

vlookup関数で例えば E1のセルに=vlookup(D1,A:C,3,false)とした場合、D1が佐藤であれば、A列に「佐藤」がある場合には当然、「佐藤」がある行の3列目の値が返されますが、「佐藤」はなく「佐藤A」や「A佐藤」がある場合にもこれらがある行の値を返して欲しいのですが、いい方法はありませんでしょうか。*を使ってできると思ったのですがうまくいきません。上記例で、=vlookup("*佐藤*",A:C,3,false)とすればできますが、*佐藤*の部分はD1の引用を利用したいのです。
 よろしくお願いします。

Aベストアンサー

=VLOOKUP("*"&D1&"*",A:C,3,FALSE)


人気Q&Aランキング

おすすめ情報