構造体をIndexOfする〜VB2008+Equalsいろいろ

  • 2010.03.31 Wednesday
  • 22:40
プログラムを作るとき、変数のまとまりを構造体として定義して作ることがある。

その構造体を配列にした場合、あの構造体のあの部分を検索したいなぁと思ったりする。
1つの変数ならIndexOfで簡単に位置が取得(検索)できるのですが、

構造体の場合、普通にIndexOfすると構造体同士の比較となってしまい、
構造体の中のあるデータに対しての比較というのはできません。

今回はその話題です。

結論から言うと、EqualsをOverrides(オーバーライズ)してあげればOKです!


ではサンプル(VB.net)

まず構造体(ここでは果物構造体)を作ります。
 
Private Structure Fruit
‌ 
    Private pFruitName As String
    Private pPrefecture As String
‌ 
    Public Sub New(ByVal srcFruitName As StringByVal srcPrefecture As String)
‌ 
        Me.pFruitName = srcFruitName
        Me.pPrefecture = srcPrefecture
‌ 
    End Sub
‌ 
'EqualsをOverridesする。この部分がIndexOfで利用される。
    Public Overrides Function Equals(ByVal obj As ObjectAs Boolean
‌ 
        Dim pF As String = CType(obj, String)’検索内容を取得
‌ 
        If pF = "" Then'空白である場合
            Return False’対象外
        Else
            If Me.pFruitName = pF Then’果物名と一致するか
                Return True’一致した
            Else
                Return False’一致しない
            End If
        End If
‌ 
    End Function
‌ 
End Structure

これで構造体の準備完了。
続いて、テスト
 
Private Sub TestIndexOf()
‌ 
    Dim intM As Int32
    Dim aFruit() As fruit = New fruit() {New fruit("りんご", "あおもり"), _
                                         New fruit("もも", "やまなし"), _
                                         New fruit("なし", "ちば"), _
                                         New fruit("さくらんぼ", "やまがた"), _
                                         New fruit("いちご", "とちぎ")}
‌ 
    intM = Array.IndexOf(aFruit, "やまがた")'-1が返る
    intM = Array.IndexOf(aFruit, "さくらんぼ")’3が返る
‌ 
End Sub

という感じで、Forループで回したりしなくてもIndexOfだけで検索が可能になります。

もちろん、IndexOfは先頭から検索をかけるので、
同じ文字がある場合は先に出てきた方のインデックス番号が返されます。

追記
構造体の比較の場合、次の方が良いようです。
 
Private Structure Fruit
        Implements System.IEquatable(Of Fruit) 'これを追加
‌ 
'同じ・・・
‌ 
'次のFunctionを追加(上を追加すると自動で生成)
    Public Overloads Function Equals(ByVal other As Fruit) As Boolean Implements System.IEquatable(Of Fruit).Equals
        If other.pFruitName = "" Then '対象がない
            Return False '不一致
        Else
            If Me.pFruitName = other.pFruitName Then '同じ
                Return True '一致
            Else
                Return False '不一致
            End If
        End If
    End Function
‌ 
End Structure

ただし、この場合は、構造体同士の比較内でFuruitNameだけを対象にした検索をしたいという場合です。

つまり、上のIEquatable(Of Fruit)を書かないで普通に次を検索すると
 
intM = Array.IndexOf(aFruit, New fruit("さくらんぼ", "やまがたけん"))’-1が返る

「やまがた」と「やまがたけん」が異なるので、検索できません。

しかし、上でユーザー独自の検索(IEquatable(Of Fruit)を作る)に変えると、
 
intM = Array.IndexOf(aFruit, New fruit("さくらんぼ", "やまがたけん"))’3が返る

「さくらんぼ」だけで比較するので、3が返ってきます。

もし、構造体同士は今まで通りで、文字列で判別したいという場合は、
上のなんでも良いObjectでの比較を行うことになる。


ところで、Fruit以外、例えば、IEquatable(Of String)と追加して、
文字列だけのFunction Equalsを作ってもその関数には入らないようなので、
Fruit構造体以外で検索したい場合は、Equals(ByVal obj As Object)を追加する必要があるようです。


※あくまでサンプルですので、細かなところはチューニングしてください。
上では
Dim FruitName As String
と宣言していますが、実際に構造体やクラスを作成する場合は、プロパティを利用してください。




追記
Equalsに絡んで、上の例以外での比較を考えたいことがある。
例えば、配列などで重複データを削除したい場合などである。

上の例ではFruitNameだけを比較しているため、Prefectureが異なっていても同じとしてしまう。
なので、Prefectureも比較したい場合別の比較が必要となる。

そういうときは、Implements IEqualityComparer(Of T)を使うと上とは別の比較が可能となる。
 
''' <summary>比較</summary>
Private Class FruitComparer
    Implements IEqualityComparer(Of Fruit)
‌ 
    ''' <summary>比較</summary>
    Public Function EqualsFruit(ByVal x As Fruit, ByVal y As Fruit) As Boolean Implements System.Collections.Generic.IEqualityComparer(Of Fruit).Equals
'クラスの場合はNothingを入れておく
        'If x Is Nothing OrElse y Is Nothing Then
        '    Return False '取得できない
        'Else
‌ 
        If x.FruitName <> y.FruitName Then
            Return False '不一致
        End If
‌ 
        If x.Prefecture <> y.Prefecture Then
            Return False '不一致
        End If
‌ 
        Return True '一致
        'End If
‌ 
    End Function
‌ 
    ''' <summary>ハッシュコード</summary>
    Public Function GetHashCodeFruit(ByVal obj As Fruit) As Integer Implements System.Collections.Generic.IEqualityComparer(Of Fruit).GetHashCode
'クラスの場合はNothingを入れておく
        'If obj Is Nothing Then
        '    Return 0I
        'Else
        Return obj.FruitName.GetHashCode
        'End If
    End Function
‌ 
End Class

というクラスを作って
 
Dim aFruit() As fruit = New fruit() {New fruit("りんご", "あおもり"), _
                                     New fruit("もも", "やまなし"), _
                                     New fruit("なし", "ちば"), _
                                     New fruit("さくらんぼ", "やまがた"), _
                                     New fruit("いちご", "とちぎ"), _
                                     New fruit("りんご", "ながの"), _
                                     New fruit("もも", "やまなし"), _
                                     New fruit("なし", "とっとり"), _
                                     New fruit("さくらんぼ", "やまがた"), _
                                     New fruit("いちご", "ふくおか")}

というデータを
aFruit.Distinct.ToArray したときと、
aFruit.Distinct(New FruitComparer).ToArray したときを比較すると、

Distinctだけでは、Prefectureに関係なくFruitNameで比較するため、
上の5つの配列だけが返されるが、FruitComparerで比較すると、ながの、とっとり、ふくおかの合計8つの配列が返される。


なお、obj.GetHashCode とすると、構造体のハッシュコードが返されるため、
a = bとしていれば同じハッシュコードが返ると思うが、
a = new Fruitとしてbと全く同じものを入れていても異なるハッシュコードが返ることがあるので、
obj.FruitName.GetHashCode(どれか基準となる値)とやっておいた方が良いようだ



参考URL
自作クラスのEqualsメソッドをオーバーライドして、等価の定義を変更する
C# Distinct IEnumerable カスタム メソッド <T> を



関連投稿
構造体をソートする〜VB2008
クラスや構造体はPublicにするかPropertyにするか〜VS2008
 

MS Office2010

  • 2010.03.25 Thursday
  • 09:33
マイクロソフトのOffice2010のアップグレードキャンペーンが始まっているようです。

優待アップグレードキャンペーン

発売はまだ未定ですが(6月頃発売という情報がありますが)、
もうまもなく発売というかんじでしょう。

ちなみに、ラインナップはこちら

で、今回の目玉(?)はWebAppsでしょうか。

要するにOfficeがなくても(インストールされていなくても)
Web上で作成、編集、共有ができるというものです。

そして、ネット環境とWindowsLiveのIDがあれば、
オフィスを無料で使えてしまうしろものです(ただし機能限定)。

まぁ、あんまり重要なファイルは置きたくないですけどね。

眠れてません

  • 2010.03.23 Tuesday
  • 05:53
このところ忙しくて寝られない毎日。今日で終わりにしたい!

まぁそうしてしまった理由を作ってしまった自分が悪いんだけれど


最近こんなCMやポスターが貼られている。

要するに政治が悪いから寝られないんじゃないの?と疑問と突っ込みを入れたい。

こんなくだらないキャンペーンを政府が行う暇があるんだったら、
バカバカしい国会を1秒でも早くやめて、ちゃんと政治を行うべきだと思う。

とりあえず、不満に1票

眠れてますか?〜睡眠キャンペーン〜

http://www8.cao.go.jp/jisatsutaisaku/suimin/index.html
http://nettv.gov-online.go.jp/prg/prg3235.html

0X8024402Cエラー〜プロキシ設定

  • 2010.03.22 Monday
  • 23:29
Microsoft Security Essentialsを使っているのだが、
先月くらいにアップデート(プログラムの)をかけた後から全く定義ファイルの更新ができなくなった。

エラーコードは0X8024402C
どうやらプロキシーで止まってしまっているらしい。


で、お願いGoogle先生で、検索すると同じ内容で困っている投稿を発見

コマンドプロンプト(管理者権限)で

netsh winhttp import proxy source=ie

を打ち込んだら、スルッと通りました。

ちなみに、Windows7です。Vista、Win8もOK
Windows Server 2008でも可
 
※このコマンドは既にIEのインターネットオプションでプロキシサーバが登録されていることが前提となります。
IEを使っていない、プロキシサーバのルートが異なる場合は、手動で設定する必要があります。


netsh winhttp set proxy proxy-server="192.168.xxx.yyy:ppp" bypass-list="192.168.xxx.*"

xxx.yyyは指定されたアドレス
pppはプロキシサーバのポート

参考
Windows Update 用の proxy を設定する方法


 
追記

XPはこちらのようです。

proxycfg -u

※上の参考URLでは /u(スラッシュ ユー)と書かれていますが、
-u (ハイフン ユー)が正しいコマンドです(下記URL参考)。

参考
Windows Update でエラー番号 0x8024402C が表示される
追記
インターネットオプションの接続→LANの設定から
設定を自動的に検出するのチェックを外すと、マシンによってはつながるみたいです。
追記2
関連なエラーが出たので、追加しておきます。

80072EFD エラー
80072EFD エラー

LANが抜けているか、設定が誤っている場合に発生します。
追記

プロキシ設定されていない場合で0X8024402Cが出てしまう場合は、
IPアドレス設定にプロバイダ等のDNSサーバー設定をしてみるとよい。

DNS

DNSは使っているプロバイダに設定方法があります。
または、ルータを返している場合は、そのルータのIPアドレスになります。
ただし、そのルータにDNSが設定されていないと解決されませんが・・・。
 
追記

Office2013のダウンロードインストールのエラーコード 12007-4 も有効です。
また、プロキシサーバがある場合は30174-4も有効でした。
 
追記

上のコマンドでプロキシを設定した後、プロキシを通さないルートでアップデートできるようになった場合、
80072EE2というエラーが出てしまう。

対処法がMSに書いてあるが、これはセキュリティ対策ソフトが入っている場合で、
上のコマンドの場合は、これでは解決できない。
Windows Update エラー 80072ee2

調べてみると、

netsh winhttp reset proxy

プロキシをリセットしてあげればOKだそうです。

ちなみに、IEの設定を使っているので、インターネットオプションのプロキシを外せば良いのでは?
と思われるかもしれませんが、設定をコピー(import)しているだけなので、
必ずresetしてあげないと解決できません。
試しに、

netsh winhttp show proxy

で設定が直接アクセス(プロキシサーバなし)になっているか確認しましょう。
プロキシサーバが設定されている場合はリセットすれば解決します。

参考
Windows Update のエラー番号 80072EE2 を解決する


関連投稿
Windows Updateのサービスが起動していない

 

win7で検索〜その2

  • 2010.03.12 Friday
  • 08:54
前回の記事こちら

ということで、悩ましいwindows7のファイル検索
いろいろ試してみると ”検索文字”(ダブルコーテーション)が使えることが分かりました。

簡単に言うなら、あいまいな表現をはっきりさせる機能(らしい)です。

まずこんなファイルがあるとします。

windows7 検索


text st t と検索すると

windows7 検索

前方一致で単語を検索するので、ごらんの通りに反応してしまいます。

ここで、ダブルコーテーションを使ってみます。
まず、tを絞ります。

text st "t"

windows7 検索

すると、tだけのファイルが絞られます。
こうしてみると単語検索(記号含まず)しているのがよく分かります。

では、さらにstで絞ります。

text "st" "t"

windows7 検索

かなり絞られてきました。

最後にtextで絞ります。

windows7 検索

こんな風に単語をはっきりさせることで、だいぶ目的のものが探しやすくなるかもしれません。


追記100315
コーテーションも使える

’検索文字’(コーテーション)も使えることが分かりました。
しかも結果がちょっと違います。
といっても、結果は何もなしとコーテーションありは同じ結果ですが・・・

左がコーテーション、右がダブルコーテーションで検索した比較

tを検索すると、
't'は先頭1文字が一致するかで検索しているのに対して(前方一致)、
"t"は単語そのものが一致しているかで検索しているようです。

ちなみに、tだけで検索した場合は't'と同じ結果が出ます。

windows7 検索

2文字で検索した場合、
これも結果は違います。
teと'te'は同じ結果です。

windows7 検索


で、検索したさいに生成される検索アドレスを確認すると、

teの場合は、

search-ms:displayname=検索場所%3A%20testtext&crumb=すべてのテキスト:te&crumb=location:C%3A%5Ctesttext

'te'の場合、

search-ms:displayname=検索場所%3A%20testtext&crumb=すべてのテキスト:'te'&crumb=location:C%3A%5Ctesttext

"te"の場合、

search-ms:displayname=検索場所%3A%20testtext&crumb=すべてのテキスト:"te"&crumb=location:C%3A%5Ctesttext

te stの場合、

search-ms:displayname=検索場所%3A%20testtext&crumb=すべてのテキスト:(te%20st)&crumb=location:C%3A%5Ctesttext

%20はスペースで検索対象には入っていないようです。
%3Aは¥マークですね。

こんな感じで検索アドレス(Web検索と似ている)を組んでいるので、
もしかすると記号もどうにかすれば検索対象に加えることができるかもしれません。




Webで検索しているとこんな内容のものがありました。
test001text.txtが検索できない
これは確かに検索できません。

なぜなら、前回の記事の通り、前方一致で単語検索仕様で考えると、
test001textはtest001textという1単語なので、textというのは途中と見なされて検索対象から外される感じです。

もし検索するなら、*textで検索ができます。

windows7 検索
ファイルを作る

windows7 検索
textで検索
※コーテーションもダブルコーテーションも検索できず

windows7 検索

*(アスタリスク)で検索すると途中検索が可能



前回の投稿
win7で検索

久々に投稿

  • 2010.03.11 Thursday
  • 00:05
ちょっと息抜き投稿

仕事の納期で切羽詰まっています

ラストスパートでがんばりマッスル!

で、そんな切羽詰まっている間に正式発表があったようですね。

FH-IIA F-17号機の打ち上げは5月18日の早朝に決まったようです。

ということで、早速作ってみました。
落下地点予報 on Google


より大きな地図で H-IIA F17 を表示

今回は東方向へ飛んでいきますので、
太平洋側にお住まいであればロケットを確認できると思います。


calendar

S M T W T F S
 123456
78910111213
14151617181920
21222324252627
28293031   
<< March 2010 >>

search this site.

よく使う、検索される投稿

categories

アマゾン

楽天

selected entries

archives

recent comment

recent trackback

profile


※当ブログはリンクフリーですが、 取材や雑誌等で掲載される場合は、事前にお知らせください

others

mobile

qrcode

powered

無料ブログ作成サービス JUGEM