[[20210831145904]] 『Dictionaryで部分一致検索をするには』(麦茶) ページの最後に飛ぶ

[ 初めての方へ | 一覧(最新更新順) | 全文検索 | 過去ログ ]

 

『Dictionaryで部分一致検索をするには』(麦茶)

'ソリューション"と"ソリューション1"という部分一致している文字を、
Dictionaryオプションで一緒の文字として格納するにはどうしたらよいのでしょうか。
↓のコードだと、別々の言葉として認識されてしまうので、良い方法を教えてください。

    For i = xx To Maxrow1
      If Not dic.exists(Cells(i, "G").Value) Then
        dic.Add key:=Cells(i, "G").Value, Item:=Cells(i, "G").Value
      End If
    Next i

< 使用 Excel:Office365、使用 OS:Windows10 >


 意図が不明なんですけど。

 ソ、ソリ、ション なんかも部分一致していると思うのですが、全部一緒の文字にするんですか?

 ソなんか、ソユーズとも一緒の文字って扱いにすることになっちゃいませんか?
 二つの文字に属することになると、厄介な事態になるの思うのですが・・?

 もう少し、詳しい事情説明が必要じゃないでしょうか?

(半平太) 2021/08/31(火) 15:18


言葉足らずですみません。
大元は"ソリューション"で、"前期ソリューション"や"ソリューション1Q"のように
その前後に何らかの文字が付く可能性があります。
(麦茶) 2021/08/31(火) 16:02

 大元が一つだと言うことは分かって、少し安心しました。

 それで、一緒に出来るとどんな良いことが起きるんでしょうか?(目的=最終的に実現したいことは何でしょうか)

 ※Dictionaryさんにとっては、それらは違うものとして認識するように作られているので、
   目的に合わせて何らかの手当が必要なんですけども。

(半平太) 2021/08/31(火) 16:43


最終的に"ソリューション"KeyのItemに{"ソリューション","前期ソリューション","ソリューション1Q"}といった配列が入った状態にしたいとかでしょうか?
(砂糖) 2021/08/31(火) 16:59

A列で同一の値がある範囲で、B列の値の種類の数>1だった場合にC列に"混在有"と表示を検索したいのです。

 A列        B列         C列
あああああ   ソリューション   混在有
あああああ   プロダクト     混在有
あああああ   プロダクト     混在有
あああああ   プロダクト     混在有


 A列        B列         C列
いいいいい   ソリューション   
いいいいい   ソリューション1Q  
いいいいい   短期ソリューション       ←この場合は"混在有"と表示しない
いいいいい   長期ソリューション
 
過去の似たような質問を真似して↓のコードを書いたのですが、
そこから部分一致にする方法に悩んでいます。

  xx = 2
  For Ct00 = xx To Maxrow00
    ひらがな00 = sheet(1).Range("A" & Ct00)
    ひらがな01 = sheet(1).Range("A" & Ct00 + 1)
    If ひらがな00 = ひらがな01 Then
    Else
      Maxrow01 = Ct00

    Dim dic As Object 'Scripting.Dictionary
    Set dic = CreateObject("Scripting.Dictionary")

    'B列のデータをDictionaryに登録
    For i = xx To Maxrow01
      If Not dic.exists(Cells(i, "B").Value) Then
        dic.Add key:=Cells(i, "B").Value, Item:=Cells(i, "B").Value
      End If
    Next i

    'MsgBox dic.Count

    For Ct01 = xx To Maxrow01
      If dic.Count > 1 Then
        With ws0.Range("X" & Ct01)
          .Value = "混在有"
          .Font.ColorIndex = 3
          .Font.Bold = True
        End With
       End If
    Next Ct01
    xx = Maxrowv1 + 1
    End If

    Set dic = Nothing

  Next Ct00
(麦茶) 2021/08/31(火) 17:05

砂糖様
はい、そうです。
(麦茶) 2021/08/31(火) 17:07

For Each key in dic.Keys
 if str = "" then
  str = key
 else
  str = str & "," & key
 end if
Next
dic("ソリューション") = Split(str,",")
とするとか
(砂糖) 2021/08/31(火) 17:28

砂糖様
記載のコードは For Ct01 = xx To Maxrow01の前に差し込めばいいですか。
また、↓のようにやってみたところ、A列が1行しかない場合でも、Msgboxが1回目は1で2回目は2になってしまうのですが、何が違うのでしょうか。

Dim str As String

For Each key In dic.Keys

 If str = "" Then

  str = key

 Else

  str = str & "," & key

 End If

Next

MsgBox dic.Count←1回目
dic("ソリューション") = Split(str, ",")
MsgBox dic.Count←2回目

(麦茶) 2021/08/31(火) 18:05


ごめんなさいあくまで一案というだけでコードがそのまま使えるわけではないです
やってることはdicに登録されているすべてのキーを","でつないだ文字列にしてSplit関数で配列に変換しているだけです
なのでそのまま使うとdicにソリューションと関係ないキーがあった場合それも配列の中に入ります
この方法でやるとしたらもう一つDictionary型変数を宣言して(仮にiDic)

strArray = Array("ソリューション", "アソシエーション", "バリエーション") '親文字列の配列
For Each strParent In strArray

 For Each i = xx to Maxrow00
  If Cells(i,"B").Value Like "*" & strParent & "*" Then
   If Not iDic.Exists(Cells(i,"B").Value) Then
    iDic.Add Cells(i,"B").Value, ""
   End If
  End If
 Next

 For Each key in iDic.Keys
  If str = "" Then
   str = key
  Else
   str = str & "," & key
  End If
 Next
 dic(strParent) = Split(str, ",")
 Set iDic = Nothing
 str = ""
Next

今エクセルが使えないので間違ってるかもしれないけどこんな感じになるんじゃないでしょうか

ちなみにdic.Countの戻り値はキーの数なのでItem内の配列の数は関係ないです
dic("ソリューション") = Split(str, ",")
のあとにCountが増えているならソリューション以外のキーが登録されているということです
Item内の配列の数を数える場合はUbound(dic(key))です
(砂糖) 2021/08/31(火) 19:06


ルールがわかりません。

 >あああああ   ソリューション   混在有

 なぜ、混在有なのですか?

 >いいいいい   短期ソリューション       ←この場合は"混在有"と表示しない

 混在有でよいのでは? 

(マナ) 2021/08/31(火) 20:28


dictionaryは使わないで書いてみました。

>A列で同一の値がある範囲で、B列の値の種類の数>1だった場合にC列に"混在有"と表示

 Option Explicit

 Sub test2()
    Dim v
    Dim k As Long, j As Long
    Dim a As String, b As String

    With Cells(1).CurrentRegion.Resize(, 5)
        .Columns(4).Formula = "=len(b1)"
        .Columns(5).Formula = "=row()"
        .Value = .Value
        .Sort .Columns(1), xlAscending, .Columns(4), xlAscending, Header:=xlYes
        v = .Value
        For k = 2 To UBound(v) - 1
            If IsEmpty(v(k, 3)) Then    '★追加しました 21:24
                a = v(k, 1)
                b = v(k, 2)
                For j = k + 1 To UBound(v):
                    If a <> v(j, 1) Then Exit For
                    If IsEmpty(v(j, 3)) Then
                        If v(j, 2) Like "*" & b & "*" Then
                             v(k, 3) = "混在有"
                             v(j, 3) = "混在有"
                        End If
                    End If
                Next
            End If
        Next
        .Value = v
        .Sort .Columns(5)
        .Offset(, 3).ClearContents
    End With

 End Sub

(マナ) 2021/08/31(火) 20:53


 数式で
 =REPT("混在有",COUNTA(UNIQUE(IF($A$2:$A$100=A2,IF(ISNUMBER(FIND("ソリューション",$B$2:$B$100)),"ソリューション",$B$2:$B$100))))>2)

 重要; 100はデータのある最終行ではなく必ずそれ以上(空白が含まれるように)に設定。
(seiya) 2021/08/31(火) 22:04

砂糖様
すみません、難しくてわからない部分が多いです。。
2か所エラーで引っかかったのですが、

 For Each i = xx to Maxrow00 ← For  i = xx to Maxrow00でよいですか。
If str = "" Then ←引数は省略できませんとでるのですが、Str変数ですか
(麦茶) 2021/09/01(水) 03:52

ご参考です。

https://detail.chiebukuro.yahoo.co.jp/qa/question_detail/q12248637077

(変なおやじ) 2021/09/01(水) 08:11


 おはようございます。ちょっと横からすみません。

 問題がまだ理解できていないので、確認です。
 |  A列             B列                 C列
 |  あああああ      ソリューション      混在有
 |  あああああ      プロダクト          混在有
 |  あああああ      プロダクト          混在有
 |  あああああ      プロダクト          混在有
 |  いいいいい      ソリューション      
 |  いいいいい      ソリューション1Q    
 |  いいいいい      短期ソリューション   ←この場合は"混在有"と表示しない
 |  いいいいい      長期ソリューション

 他のデータがあるので、ということでなく、それだけのデータの中で
 どんな結果を得たいのかを、正確に提示してもらえますか?
 (必要ならデータを追加してでも正確なものにしてください。)

 例えば、
 |  あああああ      ソリューション      混在有
 はなぜ混在有なんですか?
 |  いいいいい      ソリューション      
 のC列はなぜブランクなんですか?(あ、マナさんも指摘されていました)

 質問に確認コメントがあるんですから、それに応えるのは質問者の務めだと思います。

 そして、ルールを日本語で「正確に」列挙してください。
 大元の文字列というのは、B列のすべての項目を
 それぞれが大元だと考えて、その都度、他のデータとの関係で判断するんですよね。
 それと同一か、それを部分文字列として含むものが、A列が同一の範囲内にあれば、
 「混在有」と表示するんですね?違いますか?

 だとすれば、
    A列             B列                 C列
    あああああ      ソリューション      
    あああああ      プロダクト          混在有
    あああああ      プロダクト          混在有
    あああああ      プロダクト          混在有
    いいいいい      ソリューション      混在有
    いいいいい      ソリューション1Q    
    いいいいい      短期ソリューション  
    いいいいい      長期ソリューション  
 となるんじゃないですか?

(γ) 2021/09/01(水) 08:38


 充分説明してると思うけどなぁ。

 A列に「あああああ」が入力された行は
 「ソリューション」を含むものと「プロダクト」
 の2種類があるから、C列に【混在有】と表示、

 A列に「いいいいい」が入力された行は
 「ソリューション」を含むもの
 の1種類のみであるから、C列に何も表示しない

 ってだけの話でしょ?「ソリューション」を含むものを同じとして扱いたいって話じゃないの?
(×) 2021/09/01(水) 09:19

 なるほど、理解が追いつきました。ありがとうございます。
 つまりは、A列の値に対して、混在有り かなしかということですね。
 C列とあるので、各行ごとの判断かと誤認しました。

 それなら、
 ・A列が同じ文字列の範囲のなかで、B列の文字数最小の文字列をひとつとり、
 ・それがその範囲のB列のすべてに含まれているかどうか
 を判定すればよいということですね。

(γ) 2021/09/01(水) 10:16


 dictionaryを使った例を上げておきます。多少冗長ですが。

 Sub test()
     Dim dic  As Object
     Dim dic2 As Object
     Dim k    As Long
     Dim s    As String
     Dim key, key2
     Dim ss   As String
     Dim m    As Long

     Set dic = CreateObject("Scripting.Dictionary")

     '(1)dicのキーは A列の値。 ItemはB列の値たちをキーに持つ辞書。
     For k = 1 To Cells(Rows.Count, "A").End(xlUp).Row
         s = Cells(k, "A").Value
         If Not dic.Exists(s) Then
             Set dic(s) = CreateObject("Scripting.Dictionary")
         End If
         dic(s)(Cells(k, "B").Value) = Empty
     Next

     Set dic2 = CreateObject("Scripting.Dictionary") '混在の有無
     For Each key In dic
         '(2)長さが最小の文字列を取得(ss)
         m = 100
         For Each key2 In dic(key)
             If Len(key2) < m Then
                 m = Len(key2)
                 ss = key2
             End If
         Next

         '(3)それを含まない文字列が一つでもあれば、「混在有」
         dic2(key) = ""
         For Each key2 In dic(key)
             If InStr(key2, ss) = 0 Then
                 dic2(key) = "混在有"
                 Exit For
             End If
         Next
     Next

     ' (4)結果の書込み
     For k = 1 To Cells(Rows.Count, "A").End(xlUp).Row
         Cells(k, "C").Value = dic2(Cells(k, "A").Value)
     Next
 End Sub

(γ) 2021/09/01(水) 20:57


コメント返信:

[ 一覧(最新更新順) ]


YukiWiki 1.6.7 Copyright (C) 2000,2001 by Hiroshi Yuki. Modified by kazu.