2

int 配列があるとしましょう:

var source = new int[] { 1, 2, 3, 4, 5 };

これらの配列を使用してその一部を置き換えたい:

var fromArray = new int[] { 1, 2 };
var toArray = new int[] { 11, 12 };

上記の配列を使用して生成する必要がある出力は次のとおりです11, 12, 3, 4, 5

より高度なシナリオでは、複数の引数を使用してソースを置き換える必要がある場合もあります。とは a から来ているfromArrayと考えてください:toArrayDictionary<int[], int[]>

IEnumerable<T> Replace(IEnumerable<T> source,
                       IDictionary<IEnumerable<T>, IEnumerable<T>> values)
{
    // "values" parameter holds the pairs that I want to replace.
    // "source" can be `IList<T>` instead of `IEnumerable<T> if an indexer
    // is needed but I prefer `IEnumerable<T>`.
}

どうすればこれを達成できますか?

編集:アイテムの順序は重要です。次のように考えてくださいString.Replace。のコンテンツ全体fromArrayが存在しない場合source(たとえば、ソースに のみが1あり、 がない2場合)、メソッドはそれを置き換えようとすべきではありません。例:

var source = new int[] { 1, 2, 3, 4, 5, 6 };
var dict = new Dictionary<int[], int[]>();

// Should work, since 1 and 2 are consecutive in the source.
dict[new int[] { 1, 2 }] = new int[] { 11, 12 }; 

// There is no sequence that consists of 4 and 6, so the method should ignore it.
dict[new int[] { 4, 6 }] = new int[] { 13, 14 };

// Should work.
dict[new int[] { 5, 6 }] = new int[] { 15, 16 };

Replace(source, dict); // Output should be: 11, 12, 3, 4, 15, 16
4

5 に答える 5

1

OK、これがあなたの編集した質問に基づく答えです。もちろん、完全にテストされていません。

static IEnumerable<T> Replace<T>(IEnumerable<T> source, IDictionary<IEnumerable<T>, IEnumerable<T>> values)
{
  foreach (var kvp in values)
    source = ReplaceOne(source, kvp.Key, kvp.Value);
  return source;
}

static IEnumerable<T> ReplaceOne<T>(IEnumerable<T> source, IEnumerable<T> fromSeq, IEnumerable<T> toSeq)
{
  var sArr = source.ToArray();

  int replLength = fromSeq.Count();
  if (replLength != toSeq.Count())
    throw new NotSupportedException();

  for (int idx = 0; idx <= sArr.Length - replLength; idx++)
  {
    var testSeq = Enumerable.Range(idx, replLength).Select(i => sArr[i]);
    if (testSeq.SequenceEqual(fromSeq))
    {
      Array.Copy(toSeq.ToArray(), 0, sArr, idx, replLength);
      idx += replLength - 1;
    }
  }

  return sArr;
}
于 2012-08-11T10:18:31.620 に答える
0

IEnumerable<T>( arrays ではなく)一般的なものをサポートする必要がある場合は、次のT[]ようなものかもしれません。

IEnumerable<T> Replace<T>(IEnumerable<T> source, IEnumerable<T> fromSeq, IEnumerable<T> toSeq)
{
  var dict = fromSeq.Zip(toSeq, (fr, to) => new { Fr = fr, To = to })
    .ToDictionary(a => a.Fr, a => a.To);

  foreach (var s in source)
  {
    T replace;
    if (dict.TryGetValue(s, out replace))
      yield return replace;
    else
      yield return s;
  }
}
于 2012-08-11T09:22:49.207 に答える
0

正常に動作すると思いますが、

    void Replace<T>(ref T[] source, IDictionary<T[], T[]> values)
    {
        int start = 0;
        int index = -1;
        foreach (var item in values)
        {
            start = 0;

            while ((index = IndexOfSequence<T>(source, item.Key, start)) >= 0)
            {
                for (int i = index; i < index + item.Key.Length; i++)
                {
                    source[i] = item.Value[i - index];
                }

                start = index + item.Key.Length + 1;
            }
        }
    }

    public int IndexOfSequence<T>(T[] source, T[] sequence, int start)
    {
        int j = -1;

        if (sequence.Length == 0)
            return j;

        for (int i = start; i < source.Length; i++)
        {
            if (source[i].Equals(sequence[0]) && source.Length >= i + sequence.Length)
            {
                for (j = i + 1; j < i + sequence.Length; j++)
                {
                    if (!source[j].Equals(sequence[j - i]))
                        break;
                }

                if (j - i == sequence.Length)
                    return i;
            }
        }

        return -1;
    }
于 2012-08-11T08:52:01.593 に答える
0

あなたがlinqを愛しているなら:)

var replaced = source.Zip(fromArray.Zip(toArray, (x, y) => new {From = x, To = y}),
                                      (x, y) => new {Src = x, Dest = y}).
                Select(x => x.Src == x.Dest.From ? x.Dest.To : x.Src);
于 2012-08-11T09:08:46.090 に答える
0
IEnumerable<T> Replace(IEnumerable<T> source,
    IDictionary<IEnumerable<int>, IEnumerable<T>> values) 
{ 
    // "values" parameter holds the pairs that I want to replace. 
    // "source" can be `IList<T>` instead of `IEnumerable<T> if an indexer 
    // is needed but I prefer `IEnumerable<T>`.

    IList<T> sourceAsList = source as IList<T>;
    if (sourceAsList == null)
    {
        sourceAsList = source.ToList();
    }

    foreach (var kvp in values)
    {
        // repeat same thing as above.
    }
} 
于 2012-08-11T09:09:40.127 に答える