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

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

ただいまの
回答率

87.49%

C#で、配列に配列が含まれているかどうか知りたいです。

解決済

回答 4

投稿 編集

  • 評価
  • クリップ 1
  • VIEW 5,550
退会済みユーザー

退会済みユーザー

Windows7 Pro, Visual Studio 2013 Expressの組み合わせで、Formアプリケーションを作っています。

配列に配列が含まれているかどうか知りたいです。
//検索元の配列
string[] array = new string[] { "red", "blue", "white", "blue", "red" };

ここからblue-whiteというならびを見つけたいです。

//"blue"の位置を取得する
int index1 = Array.IndexOf(array, "blue");
//index1は1

int index2 = Array.IndexOf(array, new string[]{"blue", "white"});
//index2は-1。

どうすればよいでしょう。

List<string>でも可能でしょうか?
よろしくおねがいします。

すこし書いてみました。

//検索元の配列
string[] array = new string[] { "red", "blue", "yellow", "pink", "green",  "blue", "green" };

//"pink"の位置を取得する。3
int index1 = Array.IndexOf(array, "pink");

string[] subarray1 = new string[] { "blue", "yellow" };//成功する。1
string[] subarray2 = new string[] { "blue", "green" };//失敗する。-1
int indexarray1 = compareArray(array, subarray1);
int indexarray2 = compareArray(array, subarray2);

private int compareArray(string[] array, string[] subarray) {
    int index = Array.IndexOf(array, subarray[0]);
    bool IsSame = true;
    if (0 < index) {
        for (int i = 0; i < subarray.Length; i++, index++) {
            if (array[index] != subarray[i])                IsSame = false;
        }
    }
    if (!IsSame) return -1;
    else return index-subarray.Length;
}

これを再帰的に実行すればよいのですが。こんな方向性でしょうか?

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

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

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

    クリップを取り消します

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

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

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

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

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

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

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

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

    質問の評価を下げる

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

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

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

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

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

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

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

    詳細な説明はこちら

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

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

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

回答 4

checkベストアンサー

+4

やっつけました
効率他を考えるならまじめに実装してください

using System.Linq;
using System.Collections.Generic;
using System;

public class TEST{
    public static void Main(){
        //検索元の配列
        List<string> array = new List<string> { "red", "blue", "yellow", "pink", "green", "blue", "green", "blue", "red" };


        List<string> sub1 = new List<string> { "blue", "yellow" }; //ある
        List<string> sub2 = new List<string> { "blue", "green" }; //ある
        List<string> sub3 = new List<string> { "blue", "hoge" }; //ない

        if(array.Any(sub1))
            Console.WriteLine("sub1");
        if(array.Any(sub2))
            Console.WriteLine("sub2");
        if(array.Any(sub3))
            Console.WriteLine("sub3");
    }
}

public static class IEnumerableExtensions
{
    public static bool Any<T>(this IEnumerable<T> source, IEnumerable<T> target)
    {
        return source
            .Select((x, i) => source.Skip(i).Take(target.Count()) )
            .Any(x=>x.SequenceEqual(target));
    }
}

投稿

編集

  • 回答の評価を上げる

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

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

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

  • 回答の評価を下げる

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

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

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

  • 2016/01/13 12:51 編集

    素晴らしいです...横から失礼しますが、LINQって気持ちよく書けるなぁとしみじみ感じました。

    Select((x, i) =>).Skip(i).Take(target.Count()) ... で、おおもとの配列から1つずつ(配列の添字iを列挙して)、ずらしながら(i個分Skipしながら)、比較する配列と同じ長さの配列の配列を得て(Takeして)

    SequenceEqual() で、比較する配列と配列内各要素が一致しているかどうかをしらべて

    Any() で上記の比較で1つでも一致していれば trueを返すように

    しているのですね。

    「拡張メソッド」(array.Any() のような、オブジェクト外部からオブジェクトにメソッドを追加するような記述方法)の記法は

    http://ufcpp.net/study/csharp/sp3_extension.html

    http://www.atmarkit.co.jp/fdotnet/bookpreview/kisokaracs_1101/kisokaracs_1101_01.html

    などに説明されています。

    kaoruriderさんにとって釈迦に経の内容もあるかもしれませんが、ご容赦を。

    キャンセル

  • 2016/01/18 11:08

    お返事遅くなりました。
    先週は質問後、debugに忙殺されてしまいました。
    ozwkさん、これはすごいです。
    hskさんもおっしゃってますが、これは美しいコードです。

    うっとりしました。
    すごく幸せな気持ちになりました。

    今日は東京では雪で、電車とか大変だったのですが、すっとびました。
    いや、ほんとにきれいです。
    viva! linqですね。

    追加でお願いなのですが、現在boolを返してますけど、複数一致することもあるので、true/falseではなくて、List<int> startpoints を返すことは可能でしょうか?

    hskさん、買い被りです。かいかぶりって、かいつぶりに似てますけど、まだまだとてもこのコードをするっと理解する力はわたしにはないです。
    hskさんの解説で、なるほどと納得しました。ozwkさんへの感謝とあわせて感謝を。
    ありがとうございました。

    キャンセル

  • 2016/01/19 10:43 編集

    List<int>ではなく IEnumerable<int>ですが一応出来ました。
    .Select(...).Where(...) あたりがあまり綺麗ではないので、あとはプロにお任せします

    http://ideone.com/XMqJsQ

    ※コメントにMarkdown記法は使えないのですね。。。

    キャンセル

0

https://ideone.com/A1cTc8

投稿

  • 回答の評価を上げる

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

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

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

  • 回答の評価を下げる

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

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

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

  • 2016/01/12 17:56

    とても参考になりました。ありがとうございます。

    キャンセル

0

以前こんなQ&Aがありましたのでこれもご参考に。
https://teratail.com/questions/20408
ここの回答にあるSunday法、もしご興味があれば解説します。

投稿

  • 回答の評価を上げる

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

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

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

  • 回答の評価を下げる

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

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

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

  • 2016/01/12 17:56

    とても参考になりました。ありがとうございます。

    キャンセル

0

配列から要素の特定の並び順を一発で検索するメソッドは残念ながらArrayやListに実装されていませんので、自分でロジックを実装する必要があります。

string[] array1 = new string[] {"a", "b", "c", "d", "e", "f", "g", "h", "i", "j"};
string[] array2 = new string[] {"e", "f", "g"};
for (int i = 0; i + array2.Length < array1.Length; i++) {
    bool find = true;
    for (int j = 0; j < array2.Length; j++) {
        if (array2[j] != array1[i + j]) {
            find = false;
            break;
        }
    }
    if (find) {
        Console.WriteLine("Find at " + i);
    }
}


例えばこんな感じになるのでは。
ご参考になれば。

投稿

  • 回答の評価を上げる

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

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

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

  • 回答の評価を下げる

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

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

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

  • 2016/01/12 17:55

    ありがとうございます。

    //検索元の配列
    List<string> array = new List<string> { "red", "blue", "yellow", "pink", "green", "blue", "green", "blue", "red" };

    //"pink"の位置を取得する。3
    int index1 = Array.IndexOf(array.ToArray(), "pink");

    List<string> subarray1 = new List<string> { "blue", "yellow" };//成功する。1
    List<string> subarray2 = new List<string> { "blue", "green" };//成功する。5
    List<string> subarray3 = new List<string> { "blue", "red" };//失敗する。-1
    int indexarray1 = compareArray(array, subarray1);
    int indexarray2 = compareArray(array, subarray2);
    int indexarray3 = compareArray(array, subarray3);


    private int compareArray(List<string> array, List<string> subarray) {
    int index = Array.IndexOf(array.ToArray(), subarray[0]);
    bool IsSame = true;
    if (0 < index) {
    for (int i = 0; i < subarray.Count; i++, index++) {
    if (array[index] != subarray[i]) IsSame = false;
    }
    }
    if (!IsSame) {
    // n番目~m番目の要素を削除する
    array.RemoveRange(0, index - subarray.Count+1);
    int newindex = Array.IndexOf(array.ToArray(), subarray[0]);
    if (0 < newindex) return compareArray(array, subarray) + subarray.Count;
    else return -1;
    }
    else return index - subarray.Count;
    }

    再帰で失敗しました。

    キャンセル

  • 2016/01/12 18:02

    大した処理ではない割に、いろいろ凝りすぎな気がします。
    再帰とかはいったん忘れて、私が示したようにベタなループ処理にしたほうが可読性も高まって良いのでは。

    キャンセル

  • 2016/01/18 12:58

    たしかに。凝りすぎて動きませんでした。

    キャンセル

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

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

関連した質問

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