I have a large log file containing different record types that I want to parse. It looks something like this:
$L,8,PO
$L,8,SF
$P,8,P,0,102,0,19:08:34.463
$P,9,P,0,110,0,19:08:34.460
$P,8,P,0,105,0,19:08:34.407
$L,8,SF
$P,9,A,0,139,0,19:08:34.374
$P,15,P,0,103,0,19:08:34.532
$P,8,P,0,73,0,19:08:34.436
$L,8,SF
$L,8,PI
I'm currently using CsvHelper and followed this example of how to read multiple record types using a switch statement. I'm a bit stuck however, as I want to group the $P records depending on values contained in the $L records and then write the output to separate CSV files.
For example, the first and last $L records both contain an 8 in the second field, plus PO/PI messages (this would be the start/end of my file for all $P records containing 8 in the second field). The file output for 8.csv would look like this:
$P,8,P,0,102,0,19:08:34.463
$P,8,P,0,105,0,19:08:34.407
$P,8,P,0,73,0,19:08:34.436
In addition to grouping them together this way, I would like to prepend a number ahead of the $P record depending on the $L messages which contain SF and the number 8. There are 3 SF messages above containing SF and 8, so the final file would look something like this:
1,$P,8,P,0,102,0,19:08:34.463
1,$P,8,P,0,105,0,19:08:34.407
2,$P,8,P,0,73,0,19:08:34.436
What's the best way to accomplish this? Currently I'm adding all $P messages that contain the same ID number to a dictionary with key value pair of : List<$P Record>, and I'm not quite sure how to make the $P record groupings depend on the values of the other record.
Try something like this. It is easier to add lines to a record and then group the records.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;
namespace ConsoleApplication184
{
class Program
{
const string FILENAME = #"c:\temp\test.txt";
static void Main(string[] args)
{
int count = 0;
string line = "";
StreamReader reader = new StreamReader(FILENAME);
List<Record> records = new List<Record>();
while ((line = reader.ReadLine()) != null)
{
int startComment = line.IndexOf("//");
if (startComment >= 0)
{
line = line.Substring(0, startComment);
}
line = line.Trim();
string[] splitArray = line.Split(new char[] { ',' }).ToArray();
Record newRecord = new Record();
newRecord.car = int.Parse(splitArray[1]);
newRecord.type = (Record.RECORD_TYPE)Enum.Parse(typeof(Record.RECORD_TYPE), splitArray[2]);
records.Add(newRecord);
switch (splitArray[0])
{
case "$P":
newRecord.message = line;
break;
}
}
var cars = records.GroupBy(x => x.car);
foreach (var car in cars)
{
int lap = 0;
int stint = 0;
foreach (Record record in car)
{
record.lap = lap;
record.stint = stint;
switch (record.type)
{
case Record.RECORD_TYPE.SF:
record.lap = ++lap;
break;
case Record.RECORD_TYPE.P:
string output = string.Join(",", new string[] { record.stint.ToString(), record.lap.ToString(), record.message });
Console.WriteLine(output);
break;
case Record.RECORD_TYPE.PO :
record.stint = ++stint;
break;
}
}
}
Console.ReadLine();
}
}
public class Record
{
public enum RECORD_TYPE
{
PO,
SF,
P,
PI,
A
}
public RECORD_TYPE type { get; set; }
public int stint { get; set; }
public int lap { get; set; }
public int car { get; set; }
public string message { get; set; }
}
}
I am trying to create a bingo caller so I have a list of numbers 1-90 and it randomly picks one, moves it from the 'TobeCalled' List and into 'DeadNumbers' List, this all works fine. The problem I have is that I want to print the list as an object on the screen, so convert it to a string and print it using text apart form I get the error.
Assets\Random_Number.cs(41,17): error CS0103: The name 'String' does not exist in the current context
Here is the code:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
public class Random_Number : MonoBehaviour
{
public List <int> ListofNumbers = new List<int>(); // List of the numbers being called
public List <string> DeadNumbers = new List<string>(); // List of numbers that have been called
public Text text_to_be_Printed; // Text Element
private int numberSelected;
private string numberSelected_str;
public string DeadNumbers_str;
void Start() {
text_to_be_Printed = GetComponent<Text>();
for(int i = 1; i <= 90; i++){
ListofNumbers.Add(i); // Makes a list of all the numbers
}
}
void Update()
{
if (Input.GetKeyDown("space")){ // If space is pressed -text
numberSelected = ListofNumbers[Random.Range (0, ListofNumbers.Count)]; // Get a random number text
numberSelected_str = numberSelected.ToString();
text_to_be_Printed.text = numberSelected_str;
DeadNumbers.Add(numberSelected_str);
ListofNumbers.Remove(numberSelected);
Debug.Log(String.Join(", ", DeadNumbers));
// DeadNumbers_str = String.Join(",", DeadNumbers);
// Debug.Log(DeadNumbers_str);
}
}
}
I have tried uning String.Join but i get the error above, I'm pertty new to Unity and c# so any help would be appricated
You are missing using System; at the top of your file. String class is located at System namespace.
using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
public class Random_Number : MonoBehaviour
{
public List <int> ListofNumbers = new List<int>(); // List of the numbers being called
public List <string> DeadNumbers = new List<string>(); // List of numbers that have been called
public Text text_to_be_Printed; // Text Element
private int numberSelected;
private string numberSelected_str;
public string DeadNumbers_str;
void Start() {
text_to_be_Printed = GetComponent<Text>();
for(int i = 1; i <= 90; i++){
ListofNumbers.Add(i); // Makes a list of all the numbers
}
}
void Update()
{
if (Input.GetKeyDown("space")){ // If space is pressed -text
numberSelected = ListofNumbers[Random.Range (0, ListofNumbers.Count)]; // Get a random number text
numberSelected_str = numberSelected.ToString();
text_to_be_Printed.text = numberSelected_str;
DeadNumbers.Add(numberSelected_str);
ListofNumbers.Remove(numberSelected);
Debug.Log(String.Join(", ", DeadNumbers));
// DeadNumbers_str = String.Join(",", DeadNumbers);
// Debug.Log(DeadNumbers_str);
}
}
}
Adding to foobar's answer
string (small s) as type keyword is the same as System.String so you could also simply use string.Join instead then you don't need the using System;
I am trying to sort the two array elements and match them with one another if one any one match it returns lucky otherwise unlucky, any ideas that where i am going to wrong
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace Apptest
{
class Program
{
static void Main(string[] args)
{
int[] arr1 = { 5,4,3,8,1};
int[] arr2 = { 8,1,5,4,3};
string str = rollingdice(arr1, arr2);
Console.WriteLine(str);
}
public static string rollingdice(int[] input1, int[] input2)
{
// input1.Sort();
//input2.Sort();
for(int i=0;i<input1.Length && i<input2.Length;i++)
{
if (!Object.Equals(input1[i], input2[i]))
{
return "unlucky";
}
else
{
return "Lucky";
}
}
}
}
}
You can use Enumerable.SequenceEqual:
Array.Sort<int>(input1);
Array.Sort<int>(input2);
bool equal = input1.SequenceEqual(input2);
return equal ? "lucky" : "unlucky"; // lucky in your sample
You have to assign the result of the sorted array
var foo = input1.Sort();
var bar = input2.Sort();
Then compare foo and bar.
The shortest way to check for equality in this case would be:
bool equal = arr1.Length == arr2.Length && !arr1.Except(arr2).Any();
I have recently started learning programming and chose .NET with Visual Studio Express. I am trying to write a CSV Parser as a learning experience and it's giving me a lot more trouble than I expected. I am starting with the reader. One thing I am doing differently in my parser is that I am not using quotes. I am escaping commas with a backslash, backslashes with a backslash, and line breaks with a backslash. For example, if a comma is preceded by an even number of backslashes it is a field and I halve any blocks of backslashes. If it's odd, it's not end of field and I still halve blocks of backslashes. I'm not sure how robust this will be if I can ever get it working, except I'm only learning at this point and I'm looking at it mostly as an exercise in manipulating data structures.
I have a question in reference to the code snippet at the bottom of this post and how to make it not so static and limiting and still compile and run for me.
The line of code that reads:
var contents = (String)fileContents;
I keep trying to make it more dynamic to increase flexibility and make it something like this:
var contents = (otherVariableThatCouldChangeTypeAtRuntime.GetType())fileContents;
Is there something I can do to get it to do this and still compile? Maybe something like Option Infer from VB.NET might help, except I can't find that.
Also, I have written this in VB.NET as well. It seems to me that VB.NET allows me a considerably more dynamic style than what I've posted below, such as not having to type var over and over again and not having to keep casting my index counting variable into an integer over and over again if I shut off Option Strict and Option Explicit as well as turn on Option Infer. For example, C# won't let me type something analogous to the following VB.NET code even though I know the methods and properties I will be calling at run-time will be there at run-time.
Dim contents As Object = returnObjectICantDetermineAtComplieTime()
contents.MethodIKnowWillBeThereAtRunTime()
Can I do these things in C#? Anyways, here's the code and thanks in advance for any responses.
public class Widget
{
public object ID { get; set; }
public object PartNumber { get; set; }
public object VendorID { get; set; }
public object TypeID { get; set; }
public object KeyMarkLoc { get; set; }
public Widget() { }
}
public object ReadFromFile(object source)
{
var fileContents = new FileService().GetFileContents(source);
object records = null;
if (fileContents == null)
return null;
var stringBuffer = "";
var contents = (String)fileContents;
while (contents.Length > 0 && contents != "\r\n")
{
for (object i = 0; (int)i < contents.Length; i=(int)i+1 )
{
object character = contents[(int)i];
if (!stringBuffer.EndsWith("\r\n"))
{
stringBuffer += character.ToString();
}
if (stringBuffer.EndsWith("\r\n"))
{
var bSlashes = getBackSlashes(stringBuffer.Substring(0, stringBuffer.Length - 4));
stringBuffer = stringBuffer.Substring(0, stringBuffer.Length - 4);
if ((int)bSlashes % 2 == 0)
{
break;
}
}
}
contents = contents.Substring(stringBuffer.Length+2);
records = records == null ? getIncrementedList(new List<object>(), getNextObject(getFields(stringBuffer))) : getIncrementedList((List<object>)records, getNextObject(getFields(stringBuffer)));
}
return records;
}
private Widget getNextRecord(object[] fields)
{
var personStudent = new Widget();
personStudent.ID = fields[0];
personStudent.PartNumber = fields[1];
personStudent.VendorID = fields[2];
personStudent.TypeID = fields[3];
personStudent.GridPath = fields[4];
return personStudent;
}
private object[] getFields(object buffer)
{
var fields = new object[5];
var intFieldCount = 0;
var fieldVal = "";
var blocks = buffer.ToString().Split(',');
foreach (var block in blocks)
{
var bSlashes = getBackSlashes(block);
var intRemoveCount = (int)bSlashes / 2;
if ((int)bSlashes % 2 == 0) // Delimiter
{
fieldVal += block.Substring(0, block.Length - intRemoveCount);
fields[intFieldCount] += fieldVal;
intFieldCount++;
fieldVal = "";
}
else // Part of Field
{
fieldVal += block.Substring(0, block.Length - intRemoveCount - 1) + ",";
}
}
return fields;
}
private object getBackSlashes(object block)
{
object bSlashes = block.ToString().Length == 0 ? new int?(0) : null;
for (object i = block.ToString().Length - 1; (int)i>-1; i=(int)i-1)
{
if (block.ToString()[(int)i] != '\\') return bSlashes = bSlashes == null ? 0 : bSlashes;
bSlashes = bSlashes == null ? 1 : (int)bSlashes + 1;
}
return bSlashes;
}
}
Here is the web service code.
[WebMethod]
public object GetFileContents(object source)
{
return File.ReadAllText(source.ToString());
}
Dim contents As Object = returnObjectICantDetermineAtComplieTime()
contents.MethodIKnowWillBeThereAtRunTime()
You can do this with the dynamic type.
See for more information: http://msdn.microsoft.com/en-us/library/dd264736.aspx
As part of my University course, we've got to use ArrayLists to create a record booking system, and I want to include a way of searching for the surname of the Booking, is there a way to do this in C#?
The ArrayList contains the variable "surname", and at the moment I have this
private void search()
{
string term;
term = searchBox.Text;
foreach (string surname in dataList)
if (surname == term){
and that's where I'm stuck. Any help would be appreciated!
It is easier to use IndexOf and check if the index is not negative:
int pos = dataList.IndexOf(surname);
if (pos >= 0) {
// It's there - do whatever you need to do...
...
}
using System;
using System.Collections;
class Program
{
static void Main(string[] args)
{
ArrayList datalist = new ArrayList
{
"asd",
"surname",
"dfg"
};
Console.WriteLine(datalist.IndexOf("surname") != -1 ? "Found" : "Not found");
Console.ReadKey(true);
}
}