1

Is there any way to "automatically and fast" swap elements with a build-in fast method in a 2dimensional list, array oder dictionary in c#?

edit: to be more specific: i would not just swap 2 elements but change the order of maybe n elements / columns

I have something like this: a 2d datastracture with 10k lines (list with 10k elements) and each of those elements is again a list with 5 elements.(e.g. List of List of String>>).

  0 1 2 3 4 
0 A B C D E
1 A A A A A
2 d d c k x
3 ...
.
.
10000 ...

Is there any way to swap for all the 10k lines the element / column with index 0 and 2?

At first i would have on line 0: A B C D E and after swap: C B A D E

Or do i have to loop through all lines and swap by myself the element / column with index 0 and 2?

EDIT: In my businesslogic the 2d datastructure is going to be looped line for line and element for element and the values would be inserted somewhere. So my idea is not to loop foreach element, but to loop every line and the elements in a specific order. Since i do not want to access the elements in the order 0,1,2,3,4 but 2,1,0,3,4. Any concerns that accessing listelements in a specific order and not in a foreach manner would be slower? less performant?

edit: there is a link to java Collections.swap http://www.java-examples.com/swap-elements-java-arraylist-example

Gero
  • 12,993
  • 25
  • 65
  • 106
  • I seriously doubt there is any thing faster than writing a simple loop doing so. Why are looking for any thing faster or automatic? Elaborating that might help me understand your exact goals – fkl Jul 17 '12 at 09:30
  • Well swap is swap, you can't avoid it - you have to go through all of the data either way. – t3hn00b Jul 17 '12 at 09:35
  • because 2 of my collegues said that it is sooo easy just to swap elements / columns within lists or arrays. Ofcourse they were talking about C and not C#... But it is also an important issue because of performance within a real project. So its kinda important. – Gero Jul 17 '12 at 09:35
  • @Gero: (acc. the last edit) The order you're looping the collection doesn't matter. Simply replace the `foreach` in [my answer](http://stackoverflow.com/a/11519752/284240) with a `For-Loop` or just pass what you want to the extension: `OuterCollection[1234].Swap(0, 2);` – Tim Schmelter Jul 17 '12 at 10:07
  • +1 I think this is a good question, after all you have the `Array.Copy` method to be used to copy one array section to another which is better than a loop. – weston Aug 16 '12 at 10:53

3 Answers3

1

I think there's nothing builtin, but you can create your own extension easily:

public static class ListExtensions
{
    public static void Swap<T>(this IList<T> list, int index1, int index2)
    {
        T temp = list[index1];
        list[index1] = list[index2];
        list[index2] = temp;
    }
}

(based on Reeds Copseys approach: https://stackoverflow.com/a/1111039/284240)

Here's some sample data:

var rnd = new Random();
var hugeList = new List<List<int>>();
for (int i = 0; i < 10000; i++)
{
    var innerList = new List<int>();
    for (int ii = 0; ii < 5; ii++)
    {
        innerList.Add(rnd.Next(1,100000));
    }
    hugeList.Add(innerList);
}

Swap index 0 and 2 of all inner lists:

foreach (var innerList in hugeList)
{ 
    innerList.Swap(0, 2);
}

Note that it works for lists and arrays of any type(since both implement IList<T>).

Community
  • 1
  • 1
Tim Schmelter
  • 450,073
  • 74
  • 686
  • 939
  • btw xor is always faster than storing to a temporary on x86, and he said he cares about performance.... – Michael Graczyk Jul 17 '12 at 09:37
  • 1
    Here's mentioned that the xor-swap _it is now much slower than using a normal temporary variable_: http://www.dotnetperls.com/swap (look for "XOR swap algorithm") – Tim Schmelter Jul 17 '12 at 09:47
1

You need a data structure capable of doing this operation. I have achieved it using mixture of List<T> and Dictionary.

This way, you change order of the columns in one place and that affects everything.

public class Order
{
    public Order(int number)
    {
        Number = number;
    }

    public int Number { get; set; }
}

public class Item
{
    // ... whatever your item is 
}

public class Program
{
    static void Main()
    {
        var list = new List<Dictionary<Order, Item>>();
        var orders = new List<Order>()
                        {
                            new Order(1),
                            new Order(2),
                            new Order(3),
                            new Order(4),
                            new Order(5)
                        };

        for (int i = 0; i < 10000; i++)
        {
            list.Add( new Dictionary<Order, Item>()
                        {
                            {orders[0], new Item()},
                            {orders[1], new Item()},
                            {orders[2], new Item()},
                            {orders[3], new Item()},
                            {orders[4], new Item()}
                        });
        }

        // Now access items in order 

        var item = list[100][orders[1]];

        // now you can swap the orders: replace 2 and 4
        var temp = orders[1];
        orders[1] = orders[3];
        orders[3] = temp;

        var item = list[100][orders[1]]; // now points to previously 4th item!!
    }
}
Aliostad
  • 80,612
  • 21
  • 160
  • 208
  • looks interesting. I am just a bit worried about performance and creating that new "data structure" to fit my case. When i get my solution,i will benchmark yours and post the timings – Gero Jul 17 '12 at 11:32
0

You might like to benchmark this to see if it's better, and with 10K elements it could be.

Sudocode, not near a PC:

New temp array of size to copy
Array.Copy(from firstblock to temp)
Array.Copy(from secondblock to firstblock)
Array.Copy(from temp to secondblock)
weston
  • 54,145
  • 21
  • 145
  • 203