I am using the Apriori Algorithm to get strong rules. So far I have got them in a list box(program was found online). However now I would like to save the output to a txt file. So far all I have been getting in the .txt file is "AprioriAlgorithm.Rule". It is getting the correct number of rules, thus repeating the "AprioriAlgorithm.Rule for the number of rules. For example, if I have 12 strong rules, I get AprioriAlgoritm.Rule for 12 times in the txt file.
namespace WPFClient
{
[Export(typeof(IResult))]
public partial class Result : Window, IResult
{
public Result()
{
InitializeComponent();
}
public void Show(Output output)
{
FileStream fs = new FileStream("strongrules.txt", FileMode.Create);
StreamWriter sw = new StreamWriter(fs);
this.DataContext = output;
for (int x = 0; x < output.StrongRules.Count; x++)
{
sw.WriteLine(output.StrongRules[x]);
}
this.ShowDialog();
sw.Close();
}
}
}
And this is the output class.
namespace AprioriAlgorithm
{
using System.Collections.Generic;
public class Output
{
#region Public Properties
public IList<Rule> StrongRules { get; set; }
public IList<string> MaximalItemSets { get; set; }
public Dictionary<string, Dictionary<string, double>> ClosedItemSets { get; set; }
public ItemsDictionary FrequentItems { get; set; }
#endregion
}
}
Since you are passing object of type Rule instead of string to the WriteLine method you have to specify what exactly you want to output.
You need to override the ToString() method of your Rule class in order to do that.
public class Rule
{
public string RuleName { get; set; }
public string RuleDescription { get; set; }
public override string ToString()
{
return string.Format("{0}: {1}", RuleName, RuleDescription);
}
}
As documentation says
Writes the text representation of an object by calling the ToString method on that object, followed by a line terminator to the text string or stream.
Another way to do this (other than overriding ToString) is to output the individual properties:
var rule = output.StringRules[x];
sw.WriteLine("{0}: {1}", rule.RuleName, rule.RuleDescription);
Or, using the string interpolation feature of C#:
sw.WriteLine($"{rule.RuleName}: {rule.RuleDescription}");
You'd want to use this if you can't or don't want to override ToString.
Related
I'm reading a CSV file
Name,Score
Pat,99%
Chris,87%
and would like to discard the percent sign when the file is read through FileHelpers
using FileHelpers;
public class PctConverter : ConverterBase
{
private NumberFormatInfo nfi = new NumberFormatInfo();
public PctConverter()
{
nfi.PercentSymbol = "%";
}
public override object StringToField(string from)
{
return decimal.Parse(from, NumberStyles.Percent, nfi);
}
}
[DelimitedRecord(",")]
[IgnoreFirst]
public class Student
{
public string Name { get; set; }
public decimal Score { get; set; }
}
var student_file = "students.csv";
var engine = new FileHelperEngine<Student>();
engine.ErrorManager.ErrorMode = ErrorMode.SaveAndContinue;
List<Student> students = engine.ReadFileAsList(student_file);
ErrorInfo[] readingErrors = engine.ErrorManager.Errors;
But my converter is not quite right. Can you suggest why?
You need to specify the converter on the field you want converted, also your converter didn't work for me so I simplified it a bit:
public class PctConverter : ConverterBase
{
public override object StringToField(string from)
{
return decimal.Parse(from.Replace("%", ""));
}
}
[DelimitedRecord(",")]
[IgnoreFirst]
public class Student
{
public string Name { get; set; }
[FieldConverter(typeof(PctConverter))]
public decimal Score { get; set; }
}
I keep getting following error:
Object reference not set to an instance of an object
This is my Json string in a file at C:\part_param.json
{
"part_parameters" : {
"bar_diameter" : 300.4,
"core_height" : 132,
"roughing_offset" : 0.3
}
}
and the code I am using is as follows:
public class PLMpartParameter
{
public class Parameters
{
public float bar_diameter;
public float core_height;
public float roughing_offset;
public Parameters(float barD, float coreH, float roughingO)
{
bar_diameter = barD;
core_height = coreH;
roughing_offset = roughingO;
}
}
public Parameters parameters;
public PLMpartParameter(Parameters param)
{
parameters = param;
}
}
public static void LoadJson()
{
using (System.IO.StreamReader r = new System.IO.StreamReader(#"C:\part_param.json"))
{
string json = r.ReadToEnd();
_logger.Info(string.Format("Read entire file complete. File Values: {0}", json));
try
{
PLMpartParameter part = Newtonsoft.Json.JsonConvert.DeserializeObject<PLMpartParameter>(json);
}
catch (Exception e)
{
_logger.Info(string.Format("Read Json failed {0}", e.Message));
}
}
What am I missing here?
I think the problem is your property is called 'parameters' but in your json it's 'part_parameters'.
You must add a JSON attribute above your property, so that your properties are recognized when deserializing your object.
you will find an example just below
public class Parameters
{
[JsonProperty("bar_diameter")]
public float bar_diameter;
[JsonProperty("core_height")]
public float core_height;
[JsonProperty("roughing_offset")]
public float roughing_offset;
public Parameters(float barD, float coreH, float roughingO)
{
bar_diameter = barD;
core_height = coreH;
roughing_offset = roughingO;
}
}
Quoting Prasad Telkikar's answer as that fixed it right away
Use json2csharp to get model for your json file, then deserialize your
json. You can use visual studio in build function to create class i.e.
Edit -> Paste special -> Paste JSON as Class
Here is class
> public class PartParameters {
> public double bar_diameter { get; set; }
> public int core_height { get; set; }
> public double roughing_offset { get; set; } }
>
> public class RootObject {
> public PartParameters part_parameters { get; set; } }
To deserialize, use below code
PLMpartParameter part =
Newtonsoft.Json.JsonConvert.DeserializeObject(json);
My final code looks like this, and its working!!
public class PartParameters
{
public double bar_diameter { get; set; }
public int core_height { get; set; }
public double roughing_offset { get; set; }
}
public class RootObject
{
public PartParameters part_parameters { get; set; }
}
public static void LoadJson()
{
using (System.IO.StreamReader r = new System.IO.StreamReader(#"C:\part_param.json"))
{
string json = r.ReadToEnd();
try
{
RootObject part = Newtonsoft.Json.JsonConvert.DeserializeObject<RootObject>(json);
_logger.Info(string.Format("list values : bardiameter: {0}, coreHeight: {1}, roughingOffset: {2}",
part.part_parameters.bar_diameter,part.part_parameters.core_height, part.part_parameters.roughing_offset));
}
catch (Exception e)
{
_logger.Info(string.Format("Read Json failed {0}", e.Message));
}
}
}
You have a few issues with your code:
You need to have default constructors for the classes (this is due to how serializers work with types - they are not going to understand your class-specific paramaterised constructor).
Your fields need to be settable properties (Just add {get;set;} and you should be good to go).
I would suggest you decorate the parameters property with [JsonProperty("part_parameters")] to get the deserialization
behaviour you're expecting.
I have a class named Myclass with an override of ToString() like this:
class Field
{
}
class MyClass
{
Field propretie1
Field propretie2
.
.
.
Field propretie15
public override string ToString()
{
StringBuilder temp = new StringBuilder();
temp.Append(propretie1.ToString())
temp.Append("|");
temp.Append(propretie2.ToString())
temp.Append("|");
.
.
temp.Append(propretie15.ToString())
return temp.ToString();
}
}
I'd like to know if there is a better way to get over all the properties of Myclass with the declaration order to implement the ToString function.
No, there is no way to do this by your requirements other than coding each function manually. It would be easy with reflection, but
The GetFields method does not return fields in a particular order, such as alphabetical or declaration order. Your code must not depend on the order in which fields are returned, because that order varies.
So there is no way to actually get the order of the declaration. You could try alphabetical order by ordering them yourself though.
var allProps = typeof(MyClass).GetProperties(); // or GetFields() if they are fields
Array.Sort(allProps, (x, y) => x.Name.CompareTo(y.Name));
return string.Join("|", allProps.Select(x => x.GetValue(this)));
This uses Linq Select and an overload of GetValue from .NET 4.5 (Visual Studio 2012).
.Net offers an XmlSerializer object aimed at giving you a representation of your object.
You can take advantage of that, just grabbing text nodes and joining them:
public override string ToString()
{
return this.Stringify(); //calls reusable code to "stringify" any object
}
//converts an object's properties to a string of pipe delimited values
public static string Stringify<T>(this T obj)
{
var xs = new XmlSerializer(obj.GetType());
var doc = new XDocument();
using (var writer = doc.CreateWriter())
{
xs.Serialize(writer, obj);
}
var s = from text in doc.XPathSelectElements("//*[./text()]") select text.Value;
return string.Join("|", s);
}
Calling ToString on properties which are complex classes is more complex... to do that use the XmlElement attribute on those properties so the serializer knows you want to output these properties, then allow implicit conversion to string so the serializer doesn't error. Weirdly you also need to implement implicit conversion from string too (I guess because the serializer has the ability to deserialize too); but that doesn't have to work. Very hacky.
An alternate is to make your child type serializable using the [Serializable] attribute, put [XmlIgnore] on any public properties, then create a property with a get method calling to ToString function, and a dummy set method (again to trick the serializer). Not great, but it works.
Working Example
using System;
using System.Linq;
using System.Xml.Linq;
using System.Xml.Serialization;
using System.Xml.XPath;
namespace StackOverflow
{
public static class ObjectStringer
{
public static string Stringify<T>(this T obj)
{
var xs = new XmlSerializer(obj.GetType());
var doc = new XDocument();
using (var writer = doc.CreateWriter())
{
xs.Serialize(writer, obj);
}
var s = from text in doc.XPathSelectElements("//*[./text()]") select text.Value;
return string.Join("|", s);
}
}
public class Field
{
static int x = 0;
int y;
public Field()
{
y = ++x;
}
public override string ToString()
{
return y.ToString();
}
public static implicit operator String(Field f)
{
return f==null?null:f.ToString();
}
public static implicit operator Field(String s)
{
return s ?? "nasty hack to make serializer work";
}
}
public class Demo
{
public string P1 { get; set; }
public string X { get; set; } //something to show if we're pulling back results in order defined here, or if the system just goes alphabetically
public string P2 { get; set; }
public int P3 { get; set; }
public DateTime P4 { get; set; }
public Demo P5 { get; set; }
[XmlElement(typeof(String))]
public Field P6 { get; set; }
[XmlElement(typeof(String))]
public Field P7 { get; set; }
public override string ToString()
{
return this.Stringify();
}
}
public class Program
{
public static void Main(string[] args)
{
Demo d = new Demo() { P1 = "test1", X = "expert mode", P2 = "test2", P3 = 3, P4 = DateTime.UtcNow, P5 = new Demo() { P1 = "baby", P2 = "ooh" },P6=new Field(),P7=new Field() };
//d.P5 = d; //this solution's not perfect - e.g. attempt to serialize a circular loop in the object's graph
Console.WriteLine(d.ToString());
Console.WriteLine("done");
Console.ReadKey();
}
}
}
Alternative
[Serializable]
public class Field
{
static int x = 0;
int y;
public string DummyToString { get { return this.ToString(); } set { /*serializer hack*/ } }
[XmlIgnore]
public string DontShowMe { get; set; }
public Field()
{
y = ++x;
DontShowMe = "you shouldn't see this";
}
public override string ToString()
{
return string.Format("string me on #{0}", y);
}
}
//Demo's Field properties no longer require XmlElement attributes; i.e.:
public Field P6 { get; set; }
public Field P7 { get; set; }
NB:
If you have child items which are complex types (e.g. P5 in the above example), how do you want them handled? Should their properties also be pipe delimited (in which case how do you know which properties relate to which objects)?
How should null values be handled - same as blanks (i.e. two pipes with nothing between them), or not output at all?
Would it be better to return the property names as well as values - so you're not reliant on the order / your output's more robust to future changes in class definition?
Perhaps the XMLSerializer on its own better suits your underlying requirement; assuming you want a robust way of representing your object's data?
I have a considerable number of strings in my application that need to be cleared each time I get new data from my source. I'd like to use something akin to string.Empty, but I am unsure of how to implement this. Ideally, I'd also like to do this only once, rather than for each separate string.
Pseudo-code:
foreach (string in application)
{
this.empty
}
Am I thinking on the right track?
Some of my code is as follows:
classtoinstantiate
public string Str1;
private string str1 {get {return Str1;}}
public void DoStuff()
{
doStuff();
}
private void doStuff()
{
//dostuff
}
And Form1.cs
classtoinstantiate class1 = new classtoinstantiate();
class.DoStuff();
//I would like to then clear the *public* iteration of string Str1 here,
//before I DoStuff() again.
String.Empty represents a not null empty string.
If you want to clear a large amount of data (string/non string) you can encapsulate all of the variables in one class and create a Clean() method that goes through all the variables and clears them or instantiate that class when you need a fresh copy when you set the default values in the constructor.
The use of class.Empty is from what I understand to have a well defined instance of what is an empty instance.
Given your comments I get the feeling that you only want to clear the strings, have a look at this C# like pseudo code:
public void ClearString(IEnumerable<object> stuffToClear)
{
// go through all the objects to clear
foreach (var item in stuffToClear)
{
// get the properties to clear
var props = from prop in item.GetType().GetProperties()
where prop.PropertyType == typeof(string) // or another type or filter
select prop;
for (var p in props)
{
// clear it
p.SetValue(item, string.Empty);
}
}
}
Not that I'm writing this in freehand, all calls will surely not be correct.
That's the basic OOP concept: construct object when you need it, destroy at the end. Constructing part always deals with default values, which is exactly what you need.
For managed objects (string) simply create a new instance of a class holding all data what has to be reset (cleared):
class SomeDataStorage
{
// default is null
public string Data1 {get; set;}
private string _data2 = "default value";
public string Data2 { get {return _data2;} set {_data2 = value;}}
}
Then you construct this object when you need it
foreach (string in application)
{
var data = new SomeDataStorage(); // default values
...
}
It will be automagically destroyed when going out of scope (leaving { } or exiting function).
For unmanaged objects, implement IDisposable and consider to use using() { } often to auto-dispose.
You can have application-wide instance of SomeDataStorage. Simply assign a new object (construct new instance) to reset values to default.
To make it even more clear:
class App
{
public SomeDataStorage MyData;
public App()
{
Reset();
}
// call this when you need to init for the first time or simply reset to default
public void Reset()
{
MyData = new SomeDataStorage();
}
}
I suggest to put all your strings in to a class and dispose the object if you get new data
public class StringCollection
{
public string StringProp1 { get; set; }
public string StringProp2 { get; set; }
public string StringProp3 { get; set; }
public string StringProp4 { get; set; }
// .... more properties here
// this property won't be touched when clearing
public int SomeOtherProperty{ get; set; }
public void ClearStrings()
{
// returns all public properties
foreach (var prop in this.GetType().GetProperties())
{
// "clear" only properties of type String and those that have a public setter
if (prop.PropertyType == typeof(string) && prop.CanWrite)
prop.SetValue(this, string.Empty, null); // <- "clear" value of the property
}
}
or, in a more general manner - use extension methods:
public class StringCollection
{
public string StringProp1 { get; set; }
public string StringProp2 { get; set; }
public string StringProp3 { get; set; }
public string StringProp4 { get; set; }
public int SomeOtherProperty { get; set; }
}
public class SomeOtherClass
{
public string a1 { get; set; }
public string a2 { get; set; }
public string a3 { get; set; }
public DateTime d1 { get; set; }
public int SomeOtherProperty { get; set; }
}
public static class MyExtensions
{
public static void ClearStrings(this Object obj)
{
// returns all public properties
foreach (var prop in obj.GetType().GetProperties())
{
// "clear" only properties of type String and those that have a public setter
if (prop.PropertyType == typeof(string) && prop.CanWrite)
prop.SetValue(obj, string.Empty, null); // <- "clear" value of the property
}
}
}
use the code:
StringCollection scol2 = new StringCollection();
// ... do soemthing
scol2.ClearStrings();
SomeOtherClass obj = new SomeOtherClass();
// ... do something
obj.ClearStrings();
This question already has answers here:
Return multiple values to a method caller
(28 answers)
Closed 8 years ago.
I have a question in returning two values from a method.
I have a method from which I have to return two values. I did like this.
public string fileName(string rate,out string xmlName,out string xsdName)
{
if(rate=="2013")
{
xmlName="abc";
xsdName="def";
}
if(rate=="2014")
{
xmlName="pqr";
xsdName="xyz";
}
//stmt 1 (Here it is asking to give default values for xmlname and xsdName.But i dont want to give any default values.)
}
Now in another class I have to call this function and assign these values of xmlname and xsdName in that class. How can I do this?
public OtherClass fileName(string rate)
{
OtherClass obj = new OtherClass();
if (rate == "2013")
{
obj.xmlName = "abc";
obj.xsdName = "def";
}
if (rate == "2014")
{
obj.xmlName = "pqr";
obj.xsdName = "xyz";
}
return obj;
}
public class OtherClass
{
public string xmlName { get; set; }
public string xsdName { get; set; }
}
You'd use it like this:
string xmlName;
string xsdName;
fileName("2014", out xmlName, out xsdName);
Your fileName() method can have a return type of void since you're not technically returning anything from the function.
The best concept would be using the Objective-Oriented programming. Create a class that has two properties, xmlName and xsdName. Then return a new instance of the class from the method.
The code below should give you an idea.
Class implementation in file XmlFile.cs
public class XmlFile
{
public string XmlName
{ get; set; }
public string XsdName
{ get: set; }
}
Function implementation:
public XmlFile fileName(string rate)
{
XmlFile file = new XmlFile();
if (rate == "2013")
{
file.XmlName = "abc";
file.XsdName = "def";
}
if (rate == "2014")
{
file.XmlName = "pqr";
file.XsdName = "xyz";
}
return file;
}
Please look at OO programming in detail, you will need it with C#.
Your question is vague, but I'll try my best.
Here's how to call fileName and receive the output for the last two parameters:
string xmlName;
string xsdName;
myInstance.fileName("2014", out xmlName, out xsdName);
I tend to shy away from using out. A better solution is to create a new class that wraps the data:
public class File
{
public File(string fileName, string xmlName, string xsdName)
{
FileName = fileName;
XmlName = xmlName;
XsdName = xsdName;
}
public string FileName
{
get;
private set;
}
public string XmlName
{
get;
private set;
}
public string XsdName
{
get;
private set;
}
}
public class OtherClass
{
public File FileName(string rate)
{
switch (rate)
{
case "2013":
return new File(..., "abc", "def");
case "2014":
return new File(..., "pqr", "xyz");
default:
throw new ArgumentException(String.Format("Unexpected rate '{0}'.", rate)); // Or, simply return null
}
}
}
To call a function with out parameters:
string xmlN;
string xsdN;
var result = fileName("rate value", out xmlN, out xsdN);
But one problem is that you need to assign them before the end of the function.
In this case, setting them to null might be appropriate.
There are several possible ways to do it. First is how you do it - output parameters
string xmlName, xsdName;
filename("xxx", out xmlName, out xsdName);
Second one is to use tuples.
public Tuple<string, string> fileName(string rate)
{
...
return Tuple.Create(xmlName, xsdName)
}
Third one is to define you own class
class XmlInfo
{
public string XmlName {get; set;}
public string XsdName {get; set;}
}
XmlInfo filename(string rate)
{
...
return new XmlInfo() { XmlName = xmlName, XsdName = xsdName };
}