2012-02-17 11 views
5

In perl, la funzione di giunzione restituisce una nuova matrice di elementi da una matrice esistente e allo stesso tempo rimuove questi elementi dall'array esistente.Giuntura sulle raccolte

my @newarry = splice @oldarray, 0, 250; 

@newarray ora conterrà 250 record da @oldarray e @oldarray è di 250 record di meno.

Esiste un equivalente per le classi di raccolta C#, ad esempio Array, List, Queue, Stack con una funzione simile? Finora ho visto solo soluzioni in cui sono richiesti due passaggi (return + remove).

Update - esiste alcuna funzionalità così ho implementato un metodo extensio per supportare la funzione Splice:

public static List<T>Splice<T>(this List<T> Source, int Start, int Size) 
{ 
    List<T> retVal = Source.Skip(Start).Take(Size).ToList<T>(); 
    Source.RemoveRange(Start, Size); 
    return retVal; 
} 

Con il seguente test Unit - che succede:

[TestClass] 
public class ListTest 
{ 
    [TestMethod] 
    public void ListsSplice() 
    { 
    var lst = new List<string>() { 
     "one", 
     "two", 
     "three", 
     "four", 
     "five" 
    }; 

    var newList = lst.Splice(0, 2); 

    Assert.AreEqual(newList.Count, 2); 
    Assert.AreEqual(lst.Count, 3); 

    Assert.AreEqual(newList[0], "one"); 
    Assert.AreEqual(newList[1], "two"); 

    Assert.AreEqual(lst[0], "three"); 
    Assert.AreEqual(lst[1], "four"); 
    Assert.AreEqual(lst[2], "five"); 

    } 
} 
+1

Non esiste un equivalente diretto nelle classi di raccolta .NET. Potresti, ovviamente, scrivere il tuo metodo di supporto che restituisce + rimuovi. Come intendi usare il metodo? Forse c'è un altro modo C# di farlo, invece di provare a portare un modello da Perl. – dtb

+1

Grazie - Ho creato un metodo di estensione per aggiungere la funzione di splicing alle liste - questo potrebbe anche essere ulteriormente generalizzato per supportare IEnumerables. – SADeveloper

+0

È possibile sostituire 'Source.Skip (Start) .Take (Size) .ToList ()' di 'Source.GetRange (Start, Size)'. – Henrik

risposta

0

C'è solo Stack.Pop() e Queue.Dequeue() che restituirà e rimuoverà un articolo ma non più.

Se hai bisogno di questo comportamento devi scriverlo sul tuo, ma forse puoi semplicemente completare uno dei precedenti. Ma dovresti definire cosa succede se l'utente definisce un numero maggiore di elementi disponibili o un numero di zero o inferiore.

2

È possibile implementare un metodo Splice con un'estensione. Questo metodo ottiene semplicemente un intervallo (che è una copia dell'oggetto referenziato nell'elenco), quindi rimuove gli oggetti dall'elenco.

using System; 
using System.Collections.Generic; 
using System.Linq; 
using System.Text; 
using System.Threading.Tasks; 

namespace SpliceExample 
{ 
    class Program 
    { 
     static void Main(string[] args) 
     { 
      List<int> numbers = new List<int> { 1, 2, 3, 4, 5, 6, 7, 8, 9 }; 

      List<int> subset = numbers.Splice(3, 3); 

      Console.WriteLine(String.Join(", ", numbers)); // Prints 1, 2, 3, 7, 8, 9 
      Console.WriteLine(String.Join(", ", subset)); // Prints 4, 5, 6 

      Console.ReadLine(); 
     } 
    } 

    static class MyExtensions 
    { 
     public static List<T> Splice<T>(this List<T> list, int index, int count) 
     { 
      List<T> range = list.GetRange(index, count); 
      list.RemoveRange(index, count); 
      return range; 
     } 
    } 
} 
0

Se il numero di elementi di splicing è più grande allora il numero di elementi in una lista, allora i metodi getRange() e removeRange() un'eccezione. La soluzione migliore è utilizzare Skip() e Take() e verificare la dimensione dell'elenco:

public static class ListExtension 
    { 
     public static List<T> Splice<T>(this List<T> source, int start, int size) 
     { 
      var items = source.Skip(start).Take(size).ToList<T>(); 
      if (source.Count >= size) 
       source.RemoveRange(start, size); 
      else 
       source.Clear(); 
      return items; 
     } 
    }