Resolved Search Data Table for Specific Values

centaur

Member
Joined
Dec 17, 2017
Messages
12
Location
Houston
Programming Experience
3-5
I have created a dynamic unit conversion Data Table, example below, and want to find specific values basically using an intersection type search. gpm_us is the reference unit, in this example, where all other units are converted based on it. For example, let's say I want the "Min" converted value of m3/hr which would give me 1.14. As mentioned, the data table will be dynamic and now I need to be able to pull conversions from the table as needed. Thanks in advanced for you help!!

Units
Min
Norm
Max
gpm_us​
5​
15​
30​
l/min​
18.93​
56.78​
113.56​
m3/hr​
1.14​
3.41​
6.81​
bbl/day​
171.43​
514.29​
1028.57​
bbl/hr​
7.14​
21.43​
42.86​
 
Would you be looking to use:


C#:
DataTable table = DataSet1.Tables["yourTable"];
DataRow[] rows = table.Select("m3/hr");

Console.WriteLine(rows["Min"]);

Not sure this is right, just thought I would take a wild stab at it. Might be a starting point for you.
 
The syntax is not correct but I'll play around with it. Thanks for giving it a shot though ConsKa! It seems like it should be a simple solution but just can't get it to work.
 
Sure those who know what they are actually doing will come in and show the way with Linq - which I expect is the proper way to do this....

For my own learning purposes though...

C#:
foreach (DataRow o in table.Select("Units = 'm3/hr'"))
            {
                  textBox1.Text = o[1].ToString();
            }

That should bring back 1.14.

Edited to remove the string reference, as I was trying different things and had that in there, but it isn't actually necessary.
 
I ended up doing it this way. It's not the best way to implement it I'm sure but it's what I have right now. If anyone can show me a better way or the LINQ way, I'd appreciate the lesson. Thanks!!

C#:
for (int row = 0; row < dt.Rows.Count; row++)
{
    if (dt.Rows[row][0].ToString() == user_selected_unit)
    {
        double min_val = Convert.ToDouble(dt.Rows[row][1].ToString());
        double norm_val = Convert.ToDouble(dt.Rows[row][2].ToString());
        double max_val = Convert.ToDouble(dt.Rows[row][3].ToString());
        break;
    }
}
 
There's no need to use LINQ. You've already got everything you need. Select returns a DataRow array and you can then get the first element from that array, if it exists.
C#:
var matchingRows = dt.Select($"Units = '{userSelectedUnit}'");

if (matchingRows.Length > 0)
{
    var firstMatchingRow = matchingRows[0];

    // Use firstMatchingRow here.
}
You could throw some LINQ in there but it is really a good idea to understand the alternatives first because then you understand better what LINQ is doing in the background.
 
There's no need to use LINQ. You've already got everything you need. Select returns a DataRow array and you can then get the first element from that array, if it exists.
C#:
var matchingRows = dt.Select($"Units = '{userSelectedUnit}'");

if (matchingRows.Length > 0)
{
    var firstMatchingRow = matchingRows[0];

    // Use firstMatchingRow here.
}
You could throw some LINQ in there but it is really a good idea to understand the alternatives first because then you understand better what LINQ is doing in the background.

JMC, is there anything wrong with my version? i.e. Does it start to fall down if you have a non-unique column? - which crossed my mind.

I tested this on my DataTable and it did return Column 2 after finding the entry in Column 1 ("Units").
 
JMC, is there anything wrong with my version? i.e. Does it start to fall down if you have a non-unique column? - which crossed my mind.

I tested this on my DataTable and it did return Column 2 after finding the entry in Column 1 ("Units").
I don't see an issue with your code. If there were multiple matches then you'd end up with the last one but the situation seems to imply that there would never be multiple matches anyway.
 
C#:
double min_val = Convert.ToDouble(dt.Rows[row][1].ToString());

I wanted to ask about this, just thinking about things I am not sure about to question to further my understanding.

Data from a DataTable - if you do not To.String the data, it appears as Datarow.System - but does it have an inherent type within the DataTable?

In a Database, you would provide the type, int, nvarchar etc, but we don't get to do that for a DataTable, but C# will provide a type to a var variable based on the right side of the assignment operator - so C# can assign types if it wants to.

In the code snippet it appears that min_val is desired as a double, and the code converts to double, but finally, makes it To.String.

In my mind, the ToString at the end would negate the double, because whatever you have made it at the start, you are changing it to a String at the end?

So min_val, were you to run the code and hover over, would be a 'string min_val' variable - and not a double min_val - as C# would need to convert it back to a string Type to contain the To.String() it has created?

I would say to all of the above....I think?
 
Personally, I think that a DataTable is the wrong data structure for this kind of thing. A Dictionary seems more appropriate:
C#:
class FlowRate
{
    public double Min { get; }
    public double Norm { get; }
    public double Max { get; }

    public FlowRate(double min, double norm, double max)
    {
        Min = min;
        Norm = norm;
        Max = max;
    }
}

Dictionary<string, FlowRate> FlowRates = new Dictionary<string, FlowRate()
{
    ["gpm_us"] = new FlowRate(5, 15, 30),
    ["l/min"] = new FlowRate(18.93, 56.78, 113.56),
    ["m3/hr"] = new FlowRate(1.14, 3.41, 6.81),
    ["bbl/day"] = new FlowRate(171.43, 514.29, 1028.57),
    ["bbl/hr"] = new FlowRate(7.14, 21.43, 42.86),
};

:

Console.WriteLine(FlowRates["m3/hr"].Norm);
 
Back
Top Bottom