2
votes

Ajout d'un tableau dans une table de données avec des colonnes limitées

Je sais déjà comment ajouter un tableau dans datatable .

public string LoadAMIReadings(string startTS, string endTS, string batch, string divCode, string cc_code)
{

    totalRec = 0;
    processedRec = 0;
    this.BATCH = batch;
    this.DIVCODE = divCode;
    this.CCCODE = cc_code;
    this.FROMDATE = startTS;
    this.TODATE = endTS;
    HESservicesDoCommandRequest obj = new HESservicesDoCommandRequest();




DataTable dt = new DataTable();
dt.Columns.Add("Application_No", typeof(string));
dt.Columns.Add("REF_NO", typeof(string));
dt.Columns.Add("METER_SERIAL_NO", typeof(string));
dt.Columns.Add("XMETER_NO", typeof(string));

// here I want to call the modified solution

int rowCount = bill.Length / dt.Columns.Count; // array bill is declared globally with 7780 values in it
for (int rowIndex = 0; rowIndex < rowCount; rowIndex++)
{
    DataRow row = dt.NewRow();
    for (int columnIndex = 0; columnIndex < dt.Columns.Count; columnIndex++)
    {
        // In case of 2 rows:

        // row 1: (0 * 4) + 0 = 0
        // row 1: (0 * 4) + 1 = 1
        // row 1: (0 * 4) + 2 = 2
        // row 1: (0 * 4) + 3 = 3

        // row 2: (1 * 4) + 0 = 4
        // row 2: (1 * 4) + 1 = 5
        // row 2: (1 * 4) + 2 = 6
        // row 2: (1 * 4) + 3 = 7

        row[columnIndex] = bill[(rowIndex * dt.Columns.Count) + columnIndex];
    }

    dt.Rows.Add(row);
}


if (dt != null && dt.Rows.Count > 0)
{
    totalRec = dt.Rows.Count;
    string ReqEnvPath = System.Configuration.ConfigurationManager.AppSettings["ReadEnvPath"].ToString();
    XElement SoapReqEnv = XElement.Load(ReqEnvPath);

    foreach (DataRow dr in dt.Rows)
    {

        string uniqueID = dr["APPLICATION_NO"].ToString();
        string meterNo = dr["METER_SERIAL_NO"].ToString();

        string timestamp = DateTime.UtcNow.ToString("o");
        StringBuilder sbArg0 = new StringBuilder();
        try
        {
            sbArg0.AppendFormat(@"<?xml version=""1.0"" encoding=""UTF-8"" ?>          " + SoapReqEnv.ToString(), uniqueID, startTS, endTS, timestamp, this.HEXURL, this.HEXUID, this.HEXPWD);
            Guid currentGuid = Guid.NewGuid();

            obj.getResponseAsync(sbArg0.ToString(), currentGuid + "$" + uniqueID);
            obj.getResponseCompleted += this.myHandler;
            string delayMS = System.Configuration.ConfigurationManager.AppSettings["DelayMS"].ToString();
            ushort delay = 1000;
            ushort.TryParse(delayMS, out delay);
            System.Threading.Thread.Sleep(delay);


        }
        catch (Exception ex)
        {
            error += "Error for UniqID:" + uniqueID + "Desc:" + ex.Message + "\n";
        }
        finally
        {
            //System.Threading.Thread.CurrentThread.Join();
        }
    }
}

return error;
}

Le code ci-dessus fonctionne parfaitement. Mais j'ai une question différente . Supposons que j'ai un tableau de 8 valeurs.

arr[0] = v1
arr[1] = v2
arr[2] = v3
arr[3] = v4

arr[4] = v1
arr[5] = v2
arr[6] = v3
arr[7] = v4

Maintenant, j'ai créé un nouveau datable avec 4 colonnes.

DataTable dt = new DataTable();

dt.Columns.Add("v1");
dt.Columns.Add("v2");
dt.Columns.Add("v3");
dt.Columns.Add("v4");

DataRow row = dt.NewRow();

Maintenant, je veux ajouter les valeurs de array dans des colonnes comme

string[] arr = {"1","2","3","4","5","6","7","8"};

Update 1 strong>

J'ai une fonction dans laquelle je veux effectuer toutes ces actions

string[] months = {"Jan" , "Feb" , "Mar" , "Apr" , "Jun"};
DataTable dt = new DataTable();
dt.Columns.Add("M1");
dt.Columns.Add("M2");
dt.Columns.Add("M3");
dt.Columns.Add("M4");
dt.Columns.Add("M5");
DataRow row = dt.NewRow();

for (int i = 0; i < months.Length; i++)
{
   row[i] = months[i];       
}

dt.Rows.Add(row);

Comment puis-je les ajouter?

p >


5 commentaires

0 <= i% 4 <= 3 fait ce que vous voulez


@dcg Pouvez-vous nous en dire un peu plus?


Ce que je veux dire, c'est que si i est votre index de tableau, alors i% 4 vous donnera un index entre 0 et 3 < / code> et vous pouvez l'utiliser pour indexer votre ligne


@dcg comme ceci for (int i = 0; i <= i% 4; i ++) ?


Pas comme ça for (int i = 0; i , si vous pouvez indexer votre ligne


3 Réponses :


1
votes

Solution 1

Exemple de code; ce n'est pas la meilleure ou la plus courte implémentation, mais c'est une mise en œuvre claire et compréhensible pour les programmeurs novices .

public static class Extensions
{
    public static IEnumerable<IEnumerable<T>> Split<T>(this T[] array, int size)
    {
        for (var i = 0; i < (float)array.Length / size; i++)
        {
            yield return array.Skip(i * size).Take(size);
        }
    }

    public static void FillDataTable<T>(this DataTable dataTable, T[] input)
    {
        IEnumerable<IEnumerable<T>> rowValues = input.Split(dataTable.Columns.Count);
        foreach (IEnumerable<T> rowValue in rowValues)
        {
            DataRow row = dataTable.NewRow();

            T[] cellValues = rowValue.ToArray();
            for (int columnIndex = 0; columnIndex < cellValues.Length; columnIndex++)
            {
                // 'Safe'-check in case the original array didn't contain enough values. The cell value will remain 'null'
                if (columnIndex < dataTable.Columns.Count)
                {
                    row[columnIndex] = cellValues[columnIndex];
                }
            }

            dataTable.Rows.Add(row);
        }
    }
}

static class Program
{
    /// <summary>
    /// The main entry point for the application.
    /// </summary>
    [STAThread]
    static void Main()
    {
        int[] input = { 1, 2, 3, 4, 5, 6, 7, 8 };

        DataTable dataTable = new DataTable();
        dataTable.Columns.Add("v1");
        dataTable.Columns.Add("v2");
        dataTable.Columns.Add("v3");
        dataTable.Columns.Add("v4");

        dataTable.FillDataTable(input);    
    }
}

Solution 2 strong>

Une solution plus avancée et sécurisée pour les bords qui utilise des méthodes d'extension pour diviser le tableau d'origine en plusieurs sous-tableaux et remplissez une table de données.

string[] arr = { "1", "2", "3", "4", "5", "6", "7" };

int rowCount = arr.Length / dt.Columns.Count;
for (int rowIndex = 0; rowIndex < rowCount; rowIndex++)
{
    DataRow row = dt.NewRow();
    for (int columnIndex = 0; columnIndex < dt.Columns.Count; columnIndex++)
    {
        // In case of 2 rows:

        // row 1: (0 * 4) + 0 = 0
        // row 1: (0 * 4) + 1 = 1
        // row 1: (0 * 4) + 2 = 2
        // row 1: (0 * 4) + 3 = 3

        // row 2: (1 * 4) + 0 = 4
        // row 2: (1 * 4) + 1 = 5
        // row 2: (1 * 4) + 2 = 6
        // row 2: (1 * 4) + 3 = 7

        row[columnIndex] = arr[(rowIndex * dt.Columns.Count) + columnIndex];
    }

    dt.Rows.Add(row);
}


8 commentaires

@Moeez Solution 2 fonctionnera en effet jusqu'à n-valeurs dans le tableau original (dans ce cas 'arr'). Si le sous-tableau ne contient pas suffisamment de valeurs, la valeur de cellule de la ligne restera vide. Si vous avez d'autres questions, n'hésitez pas à les poser.


@Ordai .. En réalité, j'ai un tableau de 7780 valeurs


@Moeez Le nombre de valeurs ne devrait pas avoir d'importance. Allez-vous ajouter ces valeurs de manière séquentielle? (donc la première ligne aura la valeur 1,2,3,4 et la seconde 5,6,7,8 comme décrit dans votre OP?) La solution 2 ne devrait pas causer de problèmes.


@Ordai .. Oui, c'est ce que je veux. Votre solution 2 me va bien mais j'ai une fonction dans laquelle je fais toutes ces choses. Pouvez-vous s'il vous plaît m'aider comment puis-je l'appeler dans ma fonction. Je mettrai à jour ma question également?


@Moeez J'ai mis à jour la Solution 2 qui est une implémentation plus générique et est capable de gérer différents types d'entrées (non seulement des tableaux de chaînes, mais également des entiers).


continuons cette discussion dans le chat .


@Moeez De rien, je suis content d'avoir pu aider.


pouvez-vous voir ma nouvelle question ?



1
votes

Ce que je veux dire, c'est que vous pouvez faire quelque chose comme ceci:

new row
row[0] = arr[0];
row[1] = arr[1];
row[2] = arr[2];
row[3] = arr[3];
new row
row[0] = arr[4];
row[1] = arr[5];
row[2] = arr[6];
row[3] = arr[7];
new row
row[0] = arr[8];
row[1] = arr[9];
row[2] = arr[10];
row[3] = arr[11];
new row
row[0] = arr[12];
row[1] = arr[13];
row[2] = arr[14];
row[3] = arr[15];
...

MODIFIER : prenez ceci comme exemple:

var arr = Enumerable.Range(1, 40).ToArray();

for (int i = 0; i < arr.Length; i++)
{
    if (i % 4 == 0) { Console.WriteLine("new row"); }
    Console.WriteLine($"row[{i % 4}] = arr[{i}];");
}


5 commentaires

Cela ne fonctionne que pour 8 valeurs plus grandes que celles qu'il donne IndexOutOfRangeException


Donnez-moi un exemple où cela se produit


J'ai ajouté 32 valeurs et après le 8 j'ai eu l'erreur


Oui, c'est exactement ce que je veux.


Alors, où est-ce que vous avez IndexOutOfRangeException ?



0
votes

Cela a fonctionné pour moi, il faut ajouter des crochets pour les cas de bord mais le concept est assez simple.

        string[] arr = { "1", "2", "3", "4", "5", "6", "7", "8" };
        DataTable dt = new DataTable();
        dt.Columns.Add("v1");
        dt.Columns.Add("v2");
        dt.Columns.Add("v3");
        dt.Columns.Add("v4");
        DataRow row = dt.NewRow();

        int col = 0;
        foreach (var val in arr)
        {
            if (col > 3)
            {
                col = 0;
                dt.Rows.Add(row);
                row = dt.NewRow();
                row[col] = val;
            }
            else
            {
                row[col] = val;
                col++;
            }
        }
        dt.Rows.Add(row);


0 commentaires