I have the following model:
[Table(Name="word")]
public partial class Word
{
[Column(IsPrimaryKey=true, Name="id")]
public int Id { get; set; }
[Column(IsPrimaryKey=true, Name="language_id")]
public int LanguageId { get; set; }
[Column(Name="translation")]
public string Translation { get; set; }
[Column(Name="category")]
public string Category { get; set; }
[Column(Name="order")]
public int Order { get; set; }
}
And the following code:
var connection = new SQLiteConnection(#"Data Source=data.sqlite3");
var context = new DataContext(connection);
context.Log = Console.Out;
var test = from w1 in context.GetTable<Word> ()
join w2 in context.GetTable<Word> () on w1.Id equals w2.Id
select new {w1 = w1.Id, w2 = w2.Id};
foreach (var i in test)
{
Console.WriteLine("Word: {0} {1}", i.w1, i.w2);
}
And the output looks like this:
SELECT w1$.[id], w2$.[id]
FROM [word] AS w1$, [word] AS w2$
WHERE (w1$.[id] = w1$.[id])
-- Context: SqlServer Model: AttributedMetaModel Build: 4.0.0.0
Word: 1 1
Word: 1 1
Word: 1 2
Word: 1 2
Word: 1 3
Word: 1 3
Word: 1 4
Word: 1 4
Word: 1 5
Word: 1 5
What is going on? Why is the join condition different from what I have specified? Is this a bug or am I doing something wrong? For what it's worth, I'm using Mono on Mac and I've compiled system.data.sqlite for Mono as described on their website.
Update:
This work-around fixes the problem:
var test = from w1 in context.GetTable<Word> ()
join w2 in context.GetTable<Word> () on w1.Id equals w2.Id
where w1.Id == w2.Id
select new {w1 = w1.Id, w2 = w2.Id};
Update 2:
Apparently, linq 2 sql works quite bad with sqlite. The recommended solution is to use Entity Framework.
I think the issue is in the SQLite driver not being able to cope with self joins too well. I just tried the same thing in SQLServer
my table looks like this
Id Language_id Translation
1 1 hello
1 2 bonjour
1 3 yo
2 1 bye
2 2 aurevoiur
2 3 laterz
and the output looks like this (i added the translation column to help see whats happening easier)
SELECT [t0].[id] AS [w1], [t0].[translation] AS [word1], [t1].[id] AS [w2],
[t1].[translation] AS [word2]
FROM [word] AS [t0]
INNER JOIN [word] AS [t1] ON [t0].[id] = [t1].[id]
-- Context: SqlProvider(Sql2008) Model: AttributedMetaModel Build: 4.0.30319.18408
Word: 1 = hello, 1 = hello
Word: 1 = bonjour, 1 = hello
Word: 1 = yo, 1 = hello
Word: 1 = hello, 1 = bonjour
Word: 1 = bonjour, 1 = bonjour
Word: 1 = yo, 1 = bonjour
Word: 1 = hello, 1 = yo
Word: 1 = bonjour, 1 = yo
Word: 1 = yo, 1 = yo
Word: 2 = bye, 2 = bye
Word: 2 = aurevoiur, 2 = bye
Word: 2 = laterz, 2 = bye
Word: 2 = bye, 2 = aurevoiur
Word: 2 = aurevoiur, 2 = aurevoiur
Word: 2 = laterz, 2 = aurevoiur
Word: 2 = bye, 2 = laterz
Word: 2 = aurevoiur, 2 = laterz
Word: 2 = laterz, 2 = laterz
which still doesn't give you the set of results you are after (its giving every combination) - but at least its doing the join.
I'd advise splitting your data into two tables if possible, have the Word table - with the Id and other single columns, and have a translations table - which contains the actual translations, and foreign keys back to the word table. I suspect the sqlite driver will cope with this better.
Related
This question already has answers here:
Reading CSV files using C#
(12 answers)
Closed last month.
I have a text file as below and I want to get only the numbers below column rank:
SKYRain LND(4) VA(x) ZZ(x) NUM(n) Rank ll ListOfNames
------- ------ ----- ----- ------ ---- -- -----------
1002 75 283680 185836 1,111.50 19268 1 Jack
4308 1100 175896 195404 751.70 6384 1 Sara
3070 252 1044788 884160 682.94 18924 1 Robert
3187 206 852280 97932 535.83 16472 1 Harry
I just want the numbers below the rank below:
19268
6384
18924
16472
Is there a way?
You have a fixed width text file. Just can simply use SubString():
public class Program{
public static void Main(){
string aLineOfYourTextFile = " 1002 75 283680 185836 1,111.50 19268 1 Jack ";
Console.WriteLine(aLineOfYourTextFile.Substring(48,5));
}
}
You can also use Split():
public class Program{
public static void Main(){
string aLineOfYourTextFile = " 1002 75 283680 185836 1,111.50 19268 1 Jack ";
var columns = aLineOfYourTextFile.Split(new[]{" "}, StringSplitOptions.RemoveEmptyEntries);
Console.WriteLine(columns[5]);
}
}
read and skip 2 lines
read next line, split on " ", select 5th entry, convert to int
repeat above till EOF
So I have this string with 4 lines:
id score ping guid name lastmsg address qport rate
--- ----- ---- ---------- --------------- ------- --------------------- ------ -----
1 11 45 176387877 Player 1 3250 101.102.103.104:555 3647 25000
2 23 61 425716719 Player 2 3250 105.106.107.108:555 5978 25000
How can I 'extract' all of these values? Like, I want to save "id", "score", "ping", "guid", "name", etc.
I have played around with a "GetBetween" function I found here. I also tried to learn the string.Split function. But I don't think I'm getting close to what I want to archive, also I don't really understand splitting a string quite yet.
I basically need to remove all of the " " empty spaces between the values, problem is, the value length may change, e.g "name".
Can someone give me an example how I could extract the values?
Thanks in advance!
RegEx.Split is your friend, and this works well enough.
void Main()
{
// fun fact, the # in front of the string means it's literal, so you
// literally get the new lines
var input =
#"id score ping guid name lastmsg address qport rate
-- - -------------------------------------------------------------------------
1 11 45 176387877 Player 1 3250 101.102.103.104:555 3647 25000
2 23 61 425716719 Player 2 3250 105.106.107.108:555 5978 25000";
//Gets you each line
var lines = input.Split('\n');
// Skip 2 because I doubt you care about the column title
// or the row with the dashes
foreach (var line in lines.Skip(2))
{
// For each line, Regex split will return an array with each entry
// Set a breakpoint with the debugger and inspect to see what I mean.
// Splits using regex - assumes at least 2 spaces between items
// so space in 'Player 1' is handled it's a fickle solution though
// Trim the line before RegEx split to avoid extra data in the split
var r = Regex.Split(line.Trim(), #"\s{2,}");
}
}
You can do this with Regex and named groups.
Sample Input
var str = #"id score ping guid name lastmsg address qport rate
--- ----- ---- ---------- --------------- ------- --------------------- ------ -----
1 11 45 176387877 Player 1 3250 101.102.103.104:555 3647 25000
2 23 61 425716719 Player 2 3250 105.106.107.108:555 5978 25000";
Regex Definition
var regex = new Regex(#"^(?<id>[\d]+)(\s{2,})(?<score>[\d]+)(\s{2,})(?<ping>[\d]+)(\s{1,})(?<guid>[\d]+)(\s{2,})(?<name>([\w]+\s[\w]+))(\s{2,})(?<lastmsg>[\d]+)(\s{2,})(?<ip>[\d.:]+)(\s{2,})(?<port>[\d]+)(\s{2,})(?<rate>[\d]+)$",RegexOptions.Compiled);
Parsing Code
var lines = str.Split(new []{Environment.NewLine},StringSplitOptions.RemoveEmptyEntries);
foreach(var line in lines)
{
var match = regex.Match(line.Trim());
if(!match.Success) continue;
Console.WriteLine($"ID = {match.Groups["id"].Value}");
Console.WriteLine($"Score = {match.Groups["score"].Value}");
Console.WriteLine($"Ping = {match.Groups["ping"].Value}");
Console.WriteLine($"Guid = {match.Groups["guid"].Value}");
Console.WriteLine($"Name = {match.Groups["name"].Value}");
Console.WriteLine($"Last Msg = {match.Groups["lastmsg"].Value}");
Console.WriteLine($"Port = {match.Groups["port"].Value}");
Console.WriteLine($"Rate = {match.Groups["rate"].Value}");
}
Output
ID = 1
Score = 11
Ping = 45
Guid = 176387877
Name = Player 1
Last Msg = 3250
Port = 3647
Rate = 25000
ID = 2
Score = 23
Ping = 61
Guid = 425716719
Name = Player 2
Last Msg = 3250
Port = 5978
Rate = 25000
Question: I have a long string and I require to find the count of occurrences of all sub strings present under that string and print a list of all sub strings and their count (if count is > 1) in decreasing order of count.
Example:
String = "abcdabcd"
Result:
Substrings Count
abcd 2
abc 2
bcd 2
ab 2
bc 2
cd 2
a 2
b 2
c 2
d 2
Problem: My string can be 5000 character long and I am not able to find a efficient way to achieve this.( Efficiency is very important for application)
Is there any algorithm present or by multi threading it is possible. please help.
Example using: Find a common string within a list of strings
void Main()
{
"abcdabcd".getAllSubstrings()
.AsParallel()
.GroupBy(x => x)
.Select(g => new {g.Key, count=g.Count()})
.Dump();
}
// Define other methods and classes here
public static class Ext
{
public static IEnumerable<string> getAllSubstrings(this string word)
{
return from charIndex1 in Enumerable.Range(0, word.Length)
from charIndex2 in Enumerable.Range(0, word.Length - charIndex1 + 1)
where charIndex2 > 0
select word.Substring(charIndex1, charIndex2);
}
}
Produces:
a 2
dabc 1
abcdabc 1
b 2
abc 2
dabcd 1
bc 2
bcda 1
abcd 2
ab 2
bcdab 1
cdabc 1
abcda 1
d 2
bcdabc 1
dab 1
bcd 2
abcdab 1
c 2
bcdabcd 1
abcdabcd 1
cd 2
da 1
cdab 1
cda 1
cdabcd 1
I need to export Entities to a CSV File using CSVHelper. I made a trial work but I would have to write every field manually. What I want is to Write a record Prepended with either an 'H' or a 'D' and end every line with a single space. My Demo models:
PersonId FirstName LastName DateOfBirth
1 Randy Smith 1968-08-31
2 Zachary Smith 2002-01-10
3 Angie Smith 1969-11-20
4 Khelzie Smith 1996-07-27
AutoId Year Make Model OwnerId
1 2000 Toyota 4Runner 1
2 1995 Ford Mustang 1
3 2014 Chevrolet Corvette Stingray Coupe 2
4 2014 Volkswagen Beetle Coupe 4
5 1980 Ford F-150 2
6 1968 Chevrolet Camaro 3
7 2000 Tonka Truck 3
8 1993 Honda Accord 4
Into a CSV File Like this:
H 1 Randy Smith 8/31/1968
D 1 2000 Toyota 4Runner
D 2 1995 Ford Mustang
H 2 Zachary Smith 1/10/2002
D 3 2014 Chevy Corevett
D 5 1980 Ford F-150
H 3 Angie Smith 11/20/1969
D 6 1968 Chevrolet Camaro
D 7 2000 Tonka Truck
H 4 Khelzie Smith 7/27/1996
D 4 2014 Volkswagen Beetle Coupe
This is the Code I finally got to work:
StreamWriter textWriter = File.CreateText(fileName);
var csv = new CsvWriter(textWriter);
csv.Configuration.Delimiter = delimiter;
csv.Configuration.QuoteNoFields = true;
// This will skip those people who don't own a vehicle
foreach (Person person in people.Where(person => person.Vehicles.Count > 0))
{
// The letter 'H' must prefix every Header line
csv.WriteField((#"H " + person.PersonId));
csv.WriteField(person.FirstName);
csv.WriteField(person.LastName);
// Headers lines must end with a single space.
csv.WriteField((person.DateOfBirth.ToShortDateString() + " "));
csv.NextRecord();
foreach (Automobile auto in person.Vehicles)
{
// The letter 'D' must prefix every Detail line
csv.WriteField((#"D " + auto.AutoId));
csv.WriteField(auto.Year);
csv.WriteField(auto.Make);
// Details lines must end with a single space.
csv.WriteField((auto.Model + " "));
csv.NextRecord();
}
}
The real tables have ~70 fields apiece.
Just for those that have as thick a skull as mine, here is a solution:
foreach (TransactionHeader header in headers)
{
csv.WriteField("H");
csv.WriteRecord(header);
csv.WriteField(" ");
csv.NextRecord();
foreach (TransactionDetail detail in header.TransactionDetail)
{
csv.WriteField("D");
csv.WriteRecord(detail);
csv.WriteField(" ");
csv.NextRecord();
}
}
Thanks to everyone who saw this as pretty obvious and patiently waited for me to bash my head down on my desk enough times and then figure this out myself.
I have a block of text that im taking from a Gedcom (Here and Here) File
The text is flat and basically broken into "nodes"
I am splitting each node on the \r char and thus subdividing it into each of its parts( amount of "lines" can vary)
I know the 0 address will always be the ID but after that everything can be anywhere so i want to test each Cell of the array to see if it contains the correct tag for me to proccess
an example of what two nodes would look like
0 #ind23815# INDI <<<<<<<<<<<<<<<<<<< Start of node 1
1 NAME Lawrence /Hucstepe/
2 DISPLAY Lawrence Hucstepe
2 GIVN Lawrence
2 SURN Hucstepe
1 POSITION -850,-210
2 BOUNDARY_RECT (-887,-177),(-813,-257)
1 SEX M
1 BIRT
2 DATE 1521
1 DEAT Y
2 DATE 1559
1 NOTE * Born: Abt 1521, Kent, England
2 CONT * Marriage: Jane Pope 17 Aug 1546, Kent, England
2 CONT * Died: Bef 1559, Kent, England
2 CONT
1 FAMS #fam08318#
0 #ind23816# INDI <<<<<<<<<<<<<<<<<<<<<<< Start of Node 2
1 NAME Jane /Pope/
2 DISPLAY Jane Pope
2 GIVN Jane
2 SURN Pope
1 POSITION -750,-210
2 BOUNDARY_RECT (-787,-177),(-713,-257)
1 SEX F
1 BIRT
2 DATE 1525
1 DEAT Y
2 DATE 1609
1 NOTE * Born: Abt 1525, Tenterden, Kent, England
2 CONT * Marriage: Lawrence Hucstepe 17 Aug 1546, Kent, England
2 CONT * Died: 23 Oct 1609
2 CONT
1 FAMS #fam08318#
0 #ind23817# INDI <<<<<<<<<<< start of Node 3
So a when im done i have an array that looks like
address , string
0 = "1 NAME Lawrence /Hucstepe/"
1 = "2 DISPLAY Lawrence Hucstepe"
2 = "2 GIVN Lawrence"
3 = "2 SURN Hucstepe"
4 = "1 POSITION -850,-210"
5 = "2 BOUNDARY_RECT (-887,-177),(-813,-257)"
6 = "1 SEX M"
7 = "1 BIRT "
8 = "1 FAMS #fam08318#"
So my question is what is the best way to search the above array to see which Cell has the SEX tag or the NAME Tag or the FAMS Tag
this is the code i have
private int FindIndexinArray(string[] Arr, string search)
{
int Val = -1;
for (int i = 0; i < Arr.Length; i++)
{
if (Arr[i].Contains(search))
{
Val = i;
}
}
return Val;
}
But it seems inefficient because i end up calling it twice to make sure it doesnt return a -1
Like so
if (FindIndexinArray(SubNode, "1 BIRT ") != -1)
{
// add birthday to Struct
I.BirthDay = SubNode[FindIndexinArray(SubNode, "1 BIRT ") + 1].Replace("2 DATE ", "").Trim();
}
sorry this is a longer post but hopefully you guys will have some expert advice
Can use the static method FindAll of the Array class:
It will return the string itself though, if that works..
string[] test = { "Sex", "Love", "Rock and Roll", "Drugs", "Computer"};
Array.FindAll(test, item => item.Contains("Sex") || item.Contains("Drugs") || item.Contains("Computer"));
The => indicates a lamda expression. Basically a method without a concrete implementation.
You can also do this if the lamda gives you the creeps.
//Declare a method
private bool HasTag(string s)
{
return s.Contains("Sex") || s.Contains("Drugs") || s.Contains("Computer");
}
string[] test = { "Sex", "Love", "Rock and Roll", "Drugs", "Computer"};
Array.FindAll(test, HasTag);
What about a simple regular expression?
^(\d)\s=\s\"\d\s(SEX|BIRT|FAMS){1}.*$
First group captures the address, second group the tag.
Also, it might be quicker to dump all array items into a string and do your regex on the whole lot at once.
"But it seems inefficient because i end up calling it twice to make sure it doesnt return a -1"
Copy the returned value to a variable before you test to prevent multiple calls.
IndexResults = FindIndexinArray(SubNode, "1 BIRT ")
if (IndexResults != -1)
{
// add birthday to Struct
I.BirthDay = SubNode[IndexResults].Replace("2 DATE ", "").Trim();
}
The for loop in method FindIndexinArray shd break once you find a match if you are interested in only the first match.