How can I make an array from a sql query result? - c#

I wan't to have an array result [1000, 0, 0, 500, 0, 0, 0, 0, 3210, 0] from 1 array and sql MySqlDataReader sdr.Read() result.
here are the arrays
ArrayList array1 = new ArrayList()[1,2,3,4,5,6,7,8,9,10];
ArrayList arrayresult = new ArrayList();
while (sdr.Read())
{
transactions.Add(new transaction_details
{
ID = Int32.Parse(sdr["ID"].ToString()),
Transdate = DateTime.Parse(sdr["Transdate"].ToString()),
Debit = Decimal.Parse(sdr["Debit"].ToString()),
TransactionName = sdr["TransactionName"].ToString()
});
}
//arrayresult.add() - what do I do with this ?
If ID in sdr["ID"].ToString() is in array1, then the result would be [ 1, 4, 9]. array1 has 10 index so for final result I want it to be [ 1, 0, 0, 4, 0, 0, 0, 0, 9, 0]. If ID does not exist, 0 will be inserted.
I need arrayresult to have this result.
var debit = [1000, 0, 0 ,500, 0, 0, 0, 0, 3210, 0];
var ID = [ 1, 0, 0, 4, 0, 0, 0, 0, 9, 0];
var date= [ "2020-01-01", 0, 0, "2020-01-02", 0, 0, 0, 0, "2020-01-03", 0];

Short linq pseudo code:
using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
public class Program
{
public static void Main()
{
List<int> inp = new List<int>(){1,4,9};
List<int> array1 = new List<int>(){1,2,3,4,5,6,7,8,9,10};
var array1Index = array1.Select((i, index) => new { Index=index, i=i }).ToList();
List<int> arrayresult = new List<int>();
var query = from p in array1Index
select inp.Contains(p.i)==true?p.i:0;
arrayresult = query.ToList();
arrayresult.ForEach(x=>{
Console.Write(x+" ");
});
}
}

Related

Can I pass both a array and a variable as parameters to a method in C#? [duplicate]

This question already has answers here:
Method parameter array default value [duplicate]
(2 answers)
Closed 1 year ago.
I am making an RPG, and I have a monster encounter function where I was adding weight and pattern to enemy attacks, and where I can edit it when calling the function:
Is it possible for arrays and variables to both be parameters in the same function? If not, are there any alternatives to achieve the same goal?
static void MonsterEncounter(float hp = 10, float speed = 3, float attack = 2, string monName = "Monster", float exp = 200F, float gold = 30, bool boss = false, bool doubleBattle = false, bool twoEnemy = false, float hpTwo = 10, float speedTwo = 10, float attackTwo = 1, string monNameTwo = "Monster 2", int teamMate = 0, string status = "Fine", string powerAttack = "Super Hit", float powerAttackHit = 10, float powerAttackHeal = 2, bool isHealing = false, bool isDefending = false, int waitTime = 0, string statusAfflict = "null", bool hasWeight = true, bool hasPattern = false, string statusTwo = "Fine",string powerAttackTwo = "Super Hit", float powerAttackHitTwo = 10, float powerAttackHealTwo = 2, bool isHealingTwo = false, bool isDefendingTwo = false, int waitTimeTwo = 0,string statusAfflictTwo = "null", bool hasWeightTwo = true, bool hasPatternTwo = false, int[] patternTwo = {1, 1, 1, 1, 1,1 ,1, 1, 1, 1}, int[] weight = {0, 0, 0, 0}, int[] pattern = {1, 1, 1, 1, 1,1 ,1, 1, 1, 1}, int[] weightTwo = {0, 0, 0, 0})
but this is relevant:
int[] patternTwo = {1, 1, 1, 1, 1,1 ,1, 1, 1, 1}, int[] weight = {0, 0, 0, 0}, int[] pattern = {1, 1, 1, 1, 1,1 ,1, 1, 1, 1}, int[] weightTwo = {0, 0, 0, 0}
But I kept getting the same error here:
main.cs(4265,254): error CS1525: Unexpected symbol '{'
main.cs(4265,255+): error CS1737: Optional parameter cannot precede required parameters
main.cs(4265,254): error CS1525: Unexpected symbol '1'
I've tried declaring the variables a different way:
int[] patternTwo = new int[10] {1, 1, 1, 1, 1, 1, 1, 1, 1, 1}, int[] weight = new int[4] {0, 0, 0, 0}, int[] pattern = new int[10] {1, 1, 1, 1, 1, 1, 1, 1, 1, 1}, int[] weightTwo = new int[4] {0, 0, 0, 0}
But it produced errors still:
main.cs(4265,255+): error CS1736: The expression being assigned to optional parameter 'patternTwo' must be a constant or default value
main.cs(4265,255+): error CS1736: The expression being assigned to optional parameter 'weight' must be a constant or default value
main.cs(4265,255+): error CS1736: The expression being assigned to optional parameter 'pattern' must be a constant or default value
main.cs(4265,255+): error CS1736: The expression being assigned to optional parameter 'weightTwo' must be a constant or default value
I searched through google, but the pages I found were either in a different Programming Language or don't cover what I was asking.
Can I pass an array as arguments to a method with variable arguments in Java?
c# method with unlimited params or method with an array or list?
Passing arrays as arguments (C# Programming Guide)
Passing arrays as arguments in C#
Is it possible for arrays and variables to both be parameters in the same function? If not, are there any alternatives to achieve the same goal?
This is not a "real" solution but more a workaround. You can set the default array value as null and then use if statements to setup your desired arrays values
static void MonsterEncounter(float hp = 10, /*[...]*/ int[] patternTwo = null, int[] weight = null, int[] pattern = null, int[] weightTwo = null){
if (patternTwo == null) { pattern = new int [] { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1}; }
//[...]
if (weightTwo == null) { weightTwo = new int[] { 0, 0, 0, 0 }; }
}
Otherwise, you can also use overloading.

List grouping dynamically

I want to group a list that includes integer List<int>.
List<CNode> cNodes
and the CNode is
public class CNode
{
public List<int> Elements;
// ...
}
I can group the cNodes like that
var groups = cNodes.GroupBy(node => node.Elements[0]);
foreach (var group in groups )
{
// ...
}
but as you see the groupping is depends the first element, I want to group it by all elements
For example if node.Elements.Count == 5 expected grouping result should be the same as for:
var groups = cNodes.GroupBy(node => new
{
A = node.Elements[0],
B = node.Elements[1],
C = node.Elements[2],
D = node.Elements[3],
E = node.Elements[4]
});
I couldn't find the solution.
Thanks.
You can use something like node.Take(5) with a proper IEqualityComparer like this:
using System;
using System.Collections.Generic;
using System.Linq;
namespace ConsoleApp
{
class Program
{
static void Main(string[] args)
{
var cNodes = new List<CNode>
{
new CNode{Elements = new List<int>{ 0, 0, 1, 1, 1 } },
new CNode{Elements = new List<int>{ 0, 0, 0, 1, 1 } },
new CNode{Elements = new List<int>{ 0, 1, 1, 0 } },
new CNode{Elements = new List<int>{ 0, 1, 1, 0, 0 } },
new CNode{Elements = new List<int>{ 0, 0, 0, 0 } },
new CNode{Elements = new List<int>{ 0, 0, 0, 0 } }
};
Console.WriteLine("\tGroup by 2:");
foreach (var group in cNodes.GroupByElements(2))
Console.WriteLine($"{string.Join("\n", group)}\n");
Console.WriteLine("\tGroup by 3:");
foreach (var group in cNodes.GroupByElements(3))
Console.WriteLine($"{string.Join("\n", group)}\n");
Console.WriteLine("\tGroup by all:");
foreach (var group in cNodes.GroupByElements())
Console.WriteLine($"{string.Join("\n", group)}\n");
}
}
static class CNodeExtensions
{
public static IEnumerable<IGrouping<IEnumerable<int>, CNode>> GroupByElements(this IEnumerable<CNode> nodes) =>
nodes.GroupByElements(nodes.Min(node => node.Elements.Count));
public static IEnumerable<IGrouping<IEnumerable<int>, CNode>> GroupByElements(this IEnumerable<CNode> nodes, int count) =>
nodes.GroupBy(node => node.Elements.Take(count), new SequenceCompare());
private class SequenceCompare : IEqualityComparer<IEnumerable<int>>
{
public bool Equals(IEnumerable<int> x, IEnumerable<int> y) => x.SequenceEqual(y);
public int GetHashCode(IEnumerable<int> obj)
{
unchecked
{
var hash = 17;
foreach (var i in obj)
hash = hash * 23 + i.GetHashCode();
return hash;
}
}
}
}
internal class CNode
{
public List<int> Elements;
public override string ToString() => string.Join(", ", Elements);
}
}
Output is:
Group by 2:
0, 0, 1, 1, 1
0, 0, 0, 1, 1
0, 0, 0, 0
0, 0, 0, 0
0, 1, 1, 0
0, 1, 1, 0, 0
Group by 3:
0, 0, 1, 1, 1
0, 0, 0, 1, 1
0, 0, 0, 0
0, 0, 0, 0
0, 1, 1, 0
0, 1, 1, 0, 0
Group by all:
0, 0, 1, 1, 1
0, 0, 0, 1, 1
0, 1, 1, 0
0, 1, 1, 0, 0
0, 0, 0, 0
0, 0, 0, 0
You wrote:
I want to group it by all elements
The solution given by Alex will only group by a limited number of elements. You said you want to group it by all elements, even if you have a CNode with 100 elements. Besides: his solution also crashes if property Elements of one of the CNodes equals null.
So let's create a solution that meets your requirement.
The return value will be a sequence of groups, where every group has a Key, which is a sequence of CNodes. All elements in the group are all source CNodes that have a property Elements equal to the Key.
With equal you mean SequenceEqual. So Elements[0] == Key[0] and Elements[1] == Key[1], etc.
And of course, you want to decide when Elements[0] equals Key[0]: do you want to compare by reference (same object)? or are two CNodes equal if they have the same property values? Or do you want to specify a IEqualityComparer<CNode>, so that you can see they are equal if they have the same Name or Id?
// overload without IEqualityComparer, calls the overload with IEqualityComparer:
IEnumerable<IGrouping<IEnumerable<Cnode>, CNode>> GroupBy(
this IEnumerable<CNode> cNodes)
{
return GroupBy(cNodes, null);
}
// overload with IEqualityComparer; use default CNode comparer if paramer equals null
IEnumerable<IGrouping<IEnumerable<Cnode>, CNode>> GroupBy(
this IEnumerable<CNode> cNodes,
IEqualityComparer<CNode> cNodeComparer)
{
// TODO: check cNodes != null
if (cNodeComparer == null) cNodeComparer = EqualityComparer<CNode>.Default;
CNodeSequenceComparer nodeSequenceComparer = new CNodeSequenceComparer()
{
CNodeComparer = cNodeComparer,
}
return sequenceComparer.GroupBy(nodeSequenceComparer);
}
You've noticed I've transferred my problem to a new EqualityComparer: this compare takes two sequences of CNodes and declares them equal if they SequenceEqual, using the provided IEqualityComparer<CNode>:
class CNodeSequenceComparer : IEqualityComparer<IEnumerable<CNode>>
{
public IEqualityComparer<CNode> CNodeComparer {get; set;}
public bool Equals(IEnumerable<CNode> x, IEnumerable<CNode> y)
{
// returns true if same sequence, using CNodeComparer
// TODO: implement
}
}
One of the things we have to keep in mind, is that your property Elements might have a value null (after all, you didn't specify that this isn't the case)
public bool Equals(IEnumerable<CNode> x, IEnumerable<CNode> y)
{
if (x == null) return y == null; // true if both null
if (y == null) return false; // false because x not null
// optimizations: true if x and y are same object; false if different types
if (Object.ReferenceEquals(x, y) return true;
if (x.GetType() != y.GetType()) return false;
return x.SequenceEquals(y, this.CNodeComparer);
}

most efficient way to search in sorted binary tree

Suppose I have a binary tree, I am give the head of the tree (left values
are smaller than the values on the right), inside the tree there are ip address, e.g:
2.1.1.7
/ \
/ \
1.1.10.17 3.4.4.5
I need to write a function that searches for this specific address.
For now what I did it's Inorder traversal like:
private HashSet<string> adr = new HashSet<string>();
void Inorder(Node root){
if(root.Left != null)
Inorder(root.Left);
adr.Add(root.Data);// <----root.Data it's an ip address (string)
if(root.Right != null)
Inorder(root.Right);
}
Constractor:
private Node root;// <--- points to the root of the addresses tree
public MyClass{
Inorder(root);
}
Finction:
bool FindAddress(string address){
return adr.Contains(address);
}
But in my method I didn't used the fact that the tree is sorted, do you have an idea for better performance idea? with loop/recursion
You could write your FindAddress function as follows to take advantage of the fact the data is sorted:
var node = FindAddress(IPAddress.Parse(searchAddress), assembledTree, new IPAddressCompare());
static Node FindAddress(IPAddress address, Node root, IComparer<IPAddress> addressCompare)
{
if (root == null) return null;
var comp = addressCompare.Compare(IPAddress.Parse(root.Data), address);
if (comp == 0) return root;
if (comp < 0) return FindAddress(address, root.Left, addressCompare);
if (comp > 0) return FindAddress(address, root.Right, addressCompare);
return null;
}
Utilising a custom comparer to compare two different IP addresses by changing their representation to an Int32, considering the bytes at the start of the address most significant.
public class IPAddressCompare : IComparer<IPAddress>
{
public int Compare(IPAddress x, IPAddress y)
{
var intA = BitConverter.ToUInt32(x.GetAddressBytes().Reverse().ToArray(), 0);
var intB = BitConverter.ToUInt32(y.GetAddressBytes().Reverse().ToArray(), 0);
return intB.CompareTo(intA);
}
}
Full example: https://dotnetfiddle.net/viRy5b
I would go with the simple list and use the Binary search with a comparer. Avoids the hastle of creating your own tree and performance is best.
using System;
using System.Collections.Generic;
using System.Net;
class app
{
static void Main()
{
List<IPAddress> sortedIPs = new List<IPAddress>();
AddToList(sortedIPs, new byte[4] { 6, 10, 54, 100 });
AddToList(sortedIPs, new byte[4] { 143, 0, 254, 10 });
AddToList(sortedIPs, new byte[4] { 48, 0, 0, 1 });
AddToList(sortedIPs, new byte[4] { 0, 0, 82, 19 });
AddToList(sortedIPs, new byte[4] { 13, 0, 254, 1 });
AddToList(sortedIPs, new byte[4] { 63, 93, 4, 111 });
AddToList(sortedIPs, new byte[4] { 98, 3, 74, 1 });
AddToList(sortedIPs, new byte[4] { 98, 4, 74, 1 });
AddToList(sortedIPs, new byte[4] { 98, 3, 14, 1 });
AddToList(sortedIPs, new byte[4] { 98, 3, 14, 2 });
AddToList(sortedIPs, new byte[4] { 7, 175, 25, 65 });
AddToList(sortedIPs, new byte[4] { 46, 86, 21, 91 });
IPAddress findAddress = new IPAddress(new byte[4] { 48, 0, 0, 1 });
int index = sortedIPs.BinarySearch(findAddress, new IPAddressComparer());
}
private static void AddToList(List<IPAddress> list, byte[] address)
{
IPAddress a1 = new IPAddress(address);
IPAddressComparer ipc = new IPAddressComparer();
int index = list.BinarySearch(a1, ipc);
if (index >= 0) throw new Exception("IP address already exists in list");
list.Insert(~index, a1);
}
public class IPAddressComparer : IComparer<IPAddress>
{
public int Compare(IPAddress x, IPAddress y)
{
byte[] xb = x.GetAddressBytes();
byte[] yb = y.GetAddressBytes();
for (int i = 0; i < 4; i++)
{
int result = xb[i].CompareTo(yb[i]);
if (result != 0) return result;
}
return 0;
}
}
}

Why does this Hidden Markov Model make this prediction?

I am trying to understand how HMM works, but I think I am missing some crucial part of information that I cannot identify. I want it to predict the next "feature"/"symbol" based on a given sequence.
int[][] sequences =
{
new[] { 10001, 15, 1, 0, 0, 10002 },
new[] { 10002, 0, 1, 0, 15, 10001 },
new[] { 101, 15, 0, 0, 0, 101},
new[] { 101, 0, 0, 0, 15, 101 },
new[] { 114, 15, 0, 1, 0, 114 },
new[] { 114, 0, 0, 1, 15, 114 },
new[] { 10001, 15, 1, 0, 0, 10002 },
new[] { 10002, 0, 1, 0, 15, 10001 },
};
var teacher = new BaumWelchLearning()
{
Topology = new Forward(6),
Tolerance = 0.0001,
};
HiddenMarkovModel hmm = teacher.Learn(sequences);
// Gives 15 instead of 114
int[] prediction = hmm.Predict(observations: new[] { 114, 15, 0, 1, 0 }, next: 1);
The next character for "114, 15, 0, 1, 0" should be 114, yet the prediction is 15. Am I doing something wrong with the topology? Do I need to define something differently?
Thanks in advance!
u can't use statistic/probabilistic to predict one single realization. The theory make sense when u use it in many occurrences. In your case
call :
int[] prediction = hmm.Predict(observations: new[] { 114, 15, 0, 1, 0 }, next: 1);
many times and see what's next observations probs. really is ...

multiple classification using Liblinear in Accord.net Framework

I need to implement multiple classification classifier using Liblinear. Accord.net machine learning framework provides all of Liblinear properties except the Crammer and Singer’s formulation for multi-class classification. This is the process.
The usual way of learning a multi-class machine is by using the MulticlassSupportVectorLearning class. This class can teach one-vs-one machines that can then be queried using either voting or elimination strategies.
As such, here is an example on how linear training can be done for multiple classes:
// Let's say we have the following data to be classified
// into three possible classes. Those are the samples:
//
double[][] inputs =
{
// input output
new double[] { 0, 1, 1, 0 }, // 0
new double[] { 0, 1, 0, 0 }, // 0
new double[] { 0, 0, 1, 0 }, // 0
new double[] { 0, 1, 1, 0 }, // 0
new double[] { 0, 1, 0, 0 }, // 0
new double[] { 1, 0, 0, 0 }, // 1
new double[] { 1, 0, 0, 0 }, // 1
new double[] { 1, 0, 0, 1 }, // 1
new double[] { 0, 0, 0, 1 }, // 1
new double[] { 0, 0, 0, 1 }, // 1
new double[] { 1, 1, 1, 1 }, // 2
new double[] { 1, 0, 1, 1 }, // 2
new double[] { 1, 1, 0, 1 }, // 2
new double[] { 0, 1, 1, 1 }, // 2
new double[] { 1, 1, 1, 1 }, // 2
};
int[] outputs = // those are the class labels
{
0, 0, 0, 0, 0,
1, 1, 1, 1, 1,
2, 2, 2, 2, 2,
};
// Create a one-vs-one multi-class SVM learning algorithm
var teacher = new MulticlassSupportVectorLearning<Linear>()
{
// using LIBLINEAR's L2-loss SVC dual for each SVM
Learner = (p) => new LinearDualCoordinateDescent()
{
Loss = Loss.L2
}
};
// Learn a machine
var machine = teacher.Learn(inputs, outputs);
// Obtain class predictions for each sample
int[] predicted = machine.Decide(inputs);
// Compute classification accuracy
double acc = new GeneralConfusionMatrix(expected: outputs, predicted: predicted).Accuracy;
You can also try to solve a multiclass decision problem using the one-vs-rest strategy. In this case, you can use the MultilabelSupportVectorLearning teaching algorithm instead of the multi-class one shown above.

Categories