简体   繁体   中英

I have a list of index to mark which position to insert to DataTable, how to iterate while insert without messing the position?

I have a List<Tuple<String, Index>> that I need to insert to DataTable

A,5  
B,8

meaning I will insert A to position 5 in DataTable, B to position 8, etc.

how do you insert to DataTable in proper position because when you do something like

foreach list in lists
{
    //do something
    dt.Rows.InsertAt(dr, position); //insert to DataTable
}

it will mess the index because every iteration, the index will not be valid anymore. I tried foreach list in lists.OrderByDescending but in some cases, it will also break.

Here's one case where OrderByDescending will break position.

A  
B  
C  
F  
G  

I have a list with (D, 3) and (E, 4) . Here's what happened if I OrderByDescending / Insert data in reverse order.

First Iteration will insert the E

A  
B  
C  
F  
E  //WRONG PLACE
G  

Second Iteration will insert the D

A  
B  
C  
D  
F  
E  //WRONG PLACE
G

You should first ensure that the list is sorted by the index ascending , for example:

lists.Sort((x1, x2) => x1.Item2.CompareTo(x2.Item2)); // omit this if the list is already sorted

Now, before you can move them to the correct postion, add the rows to the end of the DataTable with Add , for example with List.ForEach :

lists.ForEach(x => dt.Rows.Add(x.Item1)); // added to the end

Now they are at the end of the table in the correct order but at the wrong position.

int newRowsBeginAt = dt.Rows.Count - lists.Count; // where are they, at the end

Now you can iterate this list (in ascending index order) and move them to their position:

for (int i = 0; i < lists.Count; i++)
{
    int currentIndex = newRowsBeginAt + i;
    int newIndex = lists[i].Item2;
    if (currentIndex != newIndex)
    {
        DataRow row = dt.Rows[currentIndex];
        object[] data = row.ItemArray;  // need to clone it otherwise RemoveAt will delete data
        dt.Rows.RemoveAt(currentIndex); // remove it from the table
        row.ItemArray = data;           // needed to restore data
        dt.Rows.InsertAt(row, newIndex);// insert to correct position
    }
}

That works because you don't change the indexes of earlier moved rows later if you start with the lower-indexes and then move to the higher indexes.


Tested with your sample data:

DataTable dt = new DataTable();
dt.Columns.Add("Col");
dt.Rows.Add("A");
dt.Rows.Add("B");
dt.Rows.Add("C");
dt.Rows.Add("F");
dt.Rows.Add("G");


var lists = new List<Tuple<string, int>>()
{
    Tuple.Create("D", 3), Tuple.Create("E", 4)
};

If you reverse the list so that you add the ones at the end first, you should not get any issues using InsertAt .

So it appears that for the list coming in, the position values of each tuple is the "absolute" position, so-to-speak, of where that entry needs to go. If that is the case, sort the incoming tuple list by ascending position value, and then insert them in order.

The values already in the list that you are adding to appear not to matter as much, it's the incoming values that are important. With the sorted list to add, this should ensure everything ends up where they need to be.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM