Hy,
I have a csv file like that
user_name1,c:\photo\user_photo.jpg,0,0,0,0
in which every line refers a distinct object with own fileds separated from comma.
How I find a particular object knowing the user name? I use distinct user_names. And after that how I make that object, curent object that I use?
What i have done until now:
StreamReader sc = new StreamReader(#"C:\Player.csv");
String linie = sc.ReadLine();
while (!String.IsNullOrEmpty(linie))
{
string[] stringu = linie.Split(',');
Player player = new Player(stringu[0], stringu[1], int.Parse(stringu[2]), int.Parse(stringu[3]), int.Parse(stringu[4]));
players.Add(player);
linie = sc.ReadLine();
}
sc.Close();
var query = players.Where(a => a.Name == label6.Text);
}
Sincerly,
You could try to use a library, which makes easy the use of CSV files with LINQ queries. Please look here.
Firstly I'd suggest that for parsing a CSV file you don't roll your own field splitter. I'd suggest using something like the TextFieldParser (which can be used in C# by referencing Microsoft.VisualBasic).
Once you've created the parser you can use it to get the array of strings for each record represented by line in your application:
List<Players> players = new List<Players>();
var parser = new TextFieldParser();
while ( !parser.EOF )
{
string [] playerFields = parser.ReadFields();
// Create player from fields
var player = Player.FromFields(playerFields);
players.Add(player);
}
Now it really depends on whether you want to continuously query the players in the file, as if you do then getting an in-memory copy and using LINQ makes sense, else if you only want to query once then I'd simply do the check line by line.
Assuming that you do want to query multiple times then parsing the file and holding the values in a List or similar makes sense (assuming the file isn't ridiculously big).
Finally, if you has distinct user names then you could use the FirstOrDefault method in LINQ to give you the single player back that matches.
var player = players.FirstOrDefault(p => p.Name.Equals(textBox.Text));
Or if you know that you have unique player names you could just store the whole lot in a dictionary....?
if ( players.ContainsKey(textBox.Text) )
{
var player = players[textBox.Text];
}
Anyway, just some thoughts.
The only problem you have at the moment, as far as I can see, it that you say you are looking to fetch "a particular object", but in your last line you are using Where which is going to return an IEnumerable containing one, none or many such objects. If you want to fetch one uniquely named object you should use Single or SingleOrDefault, e.g.
var myPlayer = players.Single(x => x.Name == label6.Text);
The answer you have accepted has merely converted your query from method syntax to the equivalent query syntax and introduced a compilation error by attempting to convert the resulting IEnumerable<Player> to a Player.
In anticipation of a problem you may be about to have, you might also want to look into Microsoft.VisualBasic.FileIO.TextFieldParser (you'll need to add a reference to Microsoft.VisualBasic.dll), which will allow you to parse a CSV in a more robust way, i.e. handle fields containing commas etc., using something like the following:
using (var parser = new TextFieldParser(filename))
{
parser.SetDelimiters(",");
while (!parser.EndOfData)
{
var p = parser.ReadFields();
players.Add(new Player(p[0], p[1], int.Parse(p[2]), int.Parse(p[3]), int.Parse(p[4])));
}
}
Have you tried something like
Player selected_player = from pl in players
where pl.Name == label6.Text
select pl;
?
Related
After looking through various Lua interpreters for C#, it seems that only one is truly pure c# - MoonSharp. LuaInterpreter (defunct from 2009) which later became NLua depends on one of two other c# librariers KeraLua or another lib, and requires a customized lua52.dll (you can not use the one from lua.org, and). They have a bug report which is closed that says look at the readme for the download location of their customized lua52.dll, however it is absent. You are forced to download these libs from various sources and pray they work together in addition have a multi-file distribution which may have/cause compatibility issues with other programs due to several lua52.dll variations on the end users computer (assuming they will use more than just your program).
The one shining beacon of light on NLua is it's apparently popularity, however the project has not received any significant update in several years. MoonSharp on the other hand appears to be completely self-contained, yet is lacking in documentation for common tasks such as loading a table that was built with lua and working with it.
I have come up with the following code based on the singular example they provided on Git, and then duplicated on their site at moonsharp.org (whichever came first, i am unsure, but having 1 example is not sufficient) :
using System;
using System.IO;
using MoonSharp.Interpreter;
class Foo {
function Bar( string accountName, string warcraftPath ) {
string datastore = Path.Combine(warcraftPath, "WTF", "Account", accountName, "SavedVariables", "DataStore_Containers.lua";
DynValue table = Script.RunString( File.ReadAllText( datastore ) );
Console.WriteLine( table.Table.Keys.Count().ToString() );
}
}
Results in the following (code in picture is slightly different as I adjusted the pasted code here for cleanliness and to make it easier for you to reproduce the problem using the table data in the pastebin link below.)
The table I am trying to read looks like the following (simplified had to paste on pastebin due to the size exceeding 30,000 characters):
World of Warcraft - Datastore_Containers Lua table sample data
I sort of have something sort of working, it's a bit hackish, but doesn't seem to be away to loop through the values or explicitly get the subtables / values or key of the value.
Script s = new Script(CoreModules.Preset_Complete);
// hacked by appending ' return DataStore_ContainersDB ' to return the table as DoString seems to only work to run a function expecting a result to be returned.
DynValue dv = s.DoString(luaTable + "\nreturn DataStore_ContainersDB;");
Table t = dv.Table;
foreach(var v in t.Keys)
{
Console.WriteLine( v.ToPrintString() );
}
The problem is that there doesn't seem to be any way for me to enter the sub-table result sets or to explicitly access those like t["global"] or t.global.
Managed to hack and slash my way through this and come up with a working solution although it is fairly rudimentary (possible someone could take this concept and make accessing of the sub data more reasonable:
Script s = new Script(CoreModules.Preset_Complete);
DynValue dv = s.DoString(luaTable + "\nreturn DataStore_ContainersDB;");
Table t = dv.Table;
Table global;
global = t.Get("global").ToObject<Table>().Get("Characters").ToObject<Table>();
foreach (var key in global.Keys)
{
Console.WriteLine( key.ToString() );
}
The library MoonSharp appears to require and depend heavily upon the Script class which is the premise by which all other methods operate. The DoString method requires a return result or the DynValue will always be void/null . DynValue appears to be the base global handler for the entire Lua process which can handle methods (aka, that lua string could contain several methods which DynValue would expose and allow them to be called in C# returning the response as other DynValue's)
So if you wish to load a lua file that ONLY contains date in Lua's table format, you MUST append a return with the table name as the last line. This is why you see :
"\nreturn DataStore_ContainersDB;"
... as the table name is called "DataStore_ContainersDB"
Next, the result must be loaded into a fresh Table object, as DynValue is not an actual table but a class construct to hold all the various formats available (methods, tables, etc).
After it is in a Table format, you can now work with it by calling the key/value pair by the key name, number, or DynValue. In my case, since I know the original key names, I call straight through to the Table where the key names exist which I do not know and would like to work with.
Table.Get( Key )
Since this returns a DynValue, we must then convert/load the object as a table again which is made convenient using the .ToObject<> method.
The foreach loop I supplied then loops through the keys available in the sub-table located at : global > Characters > *
... which I then write the key name out to the console using key.ToString()
If there is other sub-tables, in this example (as there are), you can traverse to unknown ones using the same concept in the foreach loop by expanding on it like this :
foreach (var key in global.Keys)
{
if(IsTable(global.Get(key.String)))
{
Console.WriteLine("-------" + key.ToPrintString() + "-------");
Table characterData = global.Get(key.String).ToObject<Table>();
foreach (var characterDataField in characterData.Keys)
{
if( !IsTable(characterData.Get(characterDataField.String)))
{
Console.WriteLine(string.Format("{0} = {1}", characterDataField.ToPrintString(), characterData.Get(characterDataField.String).ToPrintString()));
}
else
{
Console.WriteLine(string.Format("{0} = {1}", characterDataField.ToPrintString(), "Table[]"));
}
}
Console.WriteLine("");
}
}
... and here is the method I wrote to quickly check if the data is a table or not . This is the IsTable() method used in the above foreach example.
private static bool IsTable(DynValue table)
{
switch (table.Type)
{
case DataType.Table:
return true;
case DataType.Boolean:
case DataType.ClrFunction:
case DataType.Function:
case DataType.Nil:
case DataType.Number:
case DataType.String:
case DataType.TailCallRequest:
case DataType.Thread:
case DataType.Tuple:
case DataType.UserData:
case DataType.Void:
case DataType.YieldRequest:
break;
}
return false;
}
I have done what I could to make this workable, however, as stated before, I do see room for improving the recursion of this. Checking the data type on every subobject, and then loading it just feels very redundant and seems like this could be simplified.
I am open to other solutions on this question, ideally in the form of some enhancement that would make this not so clunky to use.
For dealing with Tables within Tables, which is my preferred way of doing things. I came up with this.
Script s = new Script();
s.DoString(luaCode);
Table tableData = s.Globals[rootTableIndex] as Table;
for (int i = 1; i < tableData.Length + 1; i++) {
Table subTable = tableData.Get(i).Table;
//Do cool stuff here with the data
}
Granted this requires you to know the index of the Global rootTable.
For my use of this I do the following (still testing out things)
string luaCode = File.ReadAllText(Path.Combine(weaponDataPath, "rifles.Lua"));
Script script = new Script();
script.DoString(luaCode);
Gun rifle = new Gun();
Table rifleData = script.Globals["rifles"] as Table;
for (int i = 1; i < rifleData.Length + 1; i++) {
Table rifleTable = rifleData.Get(i).Table;
rifle.Name = rifleTable.Get("Name").String;
rifle.BaseDamage = (int)rifleTable.Get("BaseDamage").Number;
rifle.RoundsPerMinute = (int)rifleTable.Get("RoundsPerMinute").Number;
rifle.MaxAmmoCapacity = (int)rifleTable.Get("MaxAmmoCapacity").Number;
rifle.Caliber = rifleTable.Get("Caliber").String;
rifle.WeaponType = "RIFLE";
RiflePrototypes.Add(rifle.Name, rifle);
}
This requires some assumptions about the Tables and how the values are Named, but if you are using this for object member assignment I don't see why you would care about elements in the table that are not part of the object which you define with the assignment type.Member = table.Get(member equivalent index).member type
I'm rewriting some code and trying to use Linq whenever I can. My problem right now is a simple file import function.
The file basically looks like this:
A1
B1|1882
C1|7315808907578
B9
B1|1883
C1|4025595431639
C1|8717734091786
C1|8717734091809
C1|8717734098280
C1|8717795041874
C1|8717795060998
C1|8717795108973
B9
B1|1884
C1|4025595732071
C1|7315808887184
C1|8717734001983
B9
A9
The existing code looks like this:
line = reader.ReadLine();
string itemNo = "";
List<AltItems> list = new List<AltItems>();
while (line != null) {
posts = line.Split(postSep);
if (posts.Length == 0) { }
else if (posts[0].Equals("A1")) { }
else if (posts[0].Equals("B1"))
itemNo = posts[1];
else if (posts[0].Equals("C1")) {
string altItemNo = posts[1];
list.Add(new AltItems() { ItemNo = itemNo, AltItemNo = altItemNo });
}
line = reader.ReadLine();
}
What would the equivalent Linq query look like? Any thoughts about performance penalties rewriting this code using Linq? I also have files with multiple hierarchical levels where data from items on the first level is needed to build up items on the third level...
I would agree with Ahmed ilyas. Rewriting everything in LINQ does not mean it would work faster.
Especially, regarding string parsing, you should know that it is not supported in LINQ. This is absolutely reasonable if you think that LINQ is a query language targeting data sources of many kinds in a unified way. There are ways to do it, but they are always too indirect and I don't particularly like them. One of them, is using Scott Guthry's DynamicLinq library, the way it suggested here.
Please note that I only show you a way to do string parsing using LINQ. This does not mean that I would suggest using LINQ to replace conditional code.
Hope I helped!
Hi i am trying to get to grips with Dapper.
My situation is i want to pull two values from a query into two separate strings. Im not sure if i am going about this in the correct way, but this is what i am doing:
string sql = #"Select type, name
FROM ZipData
WHERE Zip = #zip";
using (var multi = conn.QueryMultiple(sql, new { zip = zip }))
{
string result = multi.Read<string>().SingleOrDefault();
}
And i am getting Cannot access a disposed object. Object name: 'GridReader'. when trying to read the second string.The thing is it gets the first value correctly and has both the fields in in the reader i am trying to get. Im sure im misusing the api.
What am i doing wrong here? Ive googled but can find a specific example.
You are mis-using QueryMultiple. That is defined for compound SQL statements that return multiple result sets. Something like:
SELECT Foo FROM MyTable;
SELECT Bar FROM MyOtherTable;
On the other hand, you are trying to get two different columns from a single result set, so you should just use the normal Query method:
var result = conn.Query(sql, new { zip = zip }).Single();
var type = result.type;
var name = result.name;
Query returns an enumerable (because generally a query can return multiple rows). It appears that you only want one row, however, so we invoke .Single at the end to just get that row. From there, the return type is dynamic so you can simply refer to the properies implied by the columns in your SELECT statement: type and name.
I have a piece of code which returns a Sales Order from AX. In that record im using the querySalesLine method but I'm not sure where I go from there to get all the lines attached to the order below is my code:
AxaptaRecord OrderRecord = (AxaptaRecord)ax.CallStaticClassMethod("OnlineOrder", "getSalesOrder", salesRef);
if(OrderRecord.Found)
{
AxaptaObject Lines = (AxaptaObject)OrderRecord.Call("querySalesLine");
}
How would I then use this Lines object to retrieve all of the items attached to this order? I know that the querySalesLine returns a Query object but not sure what to do next.
You should create a QueryRun object, then use that object to read the lines.
var qLines = (AxaptaObject)OrderRecord.Call("querySalesLine");
var qrLines = ax.CreateAxaptaObject("QueryRun", qLines);
To read the lines use this answer.
The Query is a static description of the query.
The QueryRun uses the query to find the records.
What I have now is the following code:
Tutorial tutorial =
(from tutorial in xmlDoc.Descendants("Tutorial")
select new Tutorial
{
Author = tutorial.Element("Author").Value,
Title = tutorial.Element("Title").Value,
Date = DateTime.Parse(tutorial.Element("Date").Value),
}).First();
myTutorial.Author = tutorial.Author;
myTutorial.Title = tutorial.Title;
myTutorial.Date = tutorial.Date;
myTutorial is passed from another method. And the code below has to 'fill' it.
The question is: Is there a way to create a LINQ query, which will assign values to the properties of an existing object, rather that creating a new one.
I would like my code to look something like this:
Tutorial tutorial =
(from tutorial in xmlDoc.Descendants("Tutorial")
select myTutorial
{
Author = tutorial.Element("Author").Value,
Title = tutorial.Element("Title").Value,
Date = DateTime.Parse(tutorial.Element("Date").Value),
});
The problem I have is:
I have an object which initially only has half of it's properties set, later I need to fill the rest of the properties. This needs to be done asynchronously.
My Approach:
I use WebClient's asynchronous method DownloadStringAsync to download XML file. In the event handler I wan't to fill an object with the properties it misses. And that's why I would like to directly pass values to my object rather than creating a new one.
Please let me know if it is not the best approach.
OK, this is pure evil:
var dropThis =
(from tutorial in xmlDoc.Descendants("Tutorial")
select new
{
Author = (myTutorial.Author = (string)tutorial.Element("Author")),
Title = (myTutorial.Title = (string)tutorial.Element("Title")),
Date = (myTutorial.Date = (DateTime)tutorial.Element("Date")),
}).First();
LINQ functional queries are actually designed in such way, that they shouldn't modify existing objects or collections, i.e. preserve state (although there are ways (hacks?) to do so).
But you can pretty easily implement reflection-based method to achieve what you want.
I noticed this question and felt the need to add another dirty solution. How about Extension methods?
public static void AddTo(this IEnumerable<Tutorial> source, Tutorial projection)
{
if (source.Count() == 0)
return;
projection.Title = source.First().Title;
projection.Author = source.First().Author;
projection.Date = source.First().Date;
}
Now you can just call it to add to your current tutorial. Also, I recommend using (string) instead of .Value so you avoid null reference exceptions.
tutorialXml
.Descendants("Tutorial")
.Select(tutorial => new Tutorial
{
Author = (string) tutorial.Element("Author"),
Title = (string) tutorial.Element("Title"),
Date = DateTime.Parse((string) tutorial.Element("Date")),
})
.AddTo(myTutorial);
Anyway, Good luck. Just wanted to add a dirty solution to this ball of mud.