How to compare and select values from string using Linq? - c#

Had a class:
class filedate
{
public int id;
public string fname;
}
Fill my list with values:
List<filedate> List = ReadList(sqlFiles);
string[] FolderFiles = System.IO.Directory.GetFiles(path2Copy);
Trying to get results:
var results = List.Where(filedate =>
FolderFiles.Any(x=>Path.GetFileNameWithoutExtension(x) ==
Path.GetFileNameWithoutExtension(filedate.fname)));
I have the same files in List and FolderFiles, but get no results in results. I am a newbie to Linq. Where is the problem?
update:
List: (count) > 1000
for example:
<1023, 'tr_F2opervag_2808_1644.dat'>
FolderFiles example:
"\\domain.corp.dns\share\folder\tr_F2opervag_2808_1644.dat"
Update 2:
found out my mistake! Comment with intersection was helpful! This code is working:
var results = List.Where(
(filedate x) =>
{
return ! FolderFiles.Any(xxx =>
Path.GetFileNameWithoutExtension(xxx) ==
Path.GetFileNameWithoutExtension(x.fname));
});

You're code works fine for me so there's something wrong with the format of your data in the List coming back from the database.
Post an example of an fname value from the filedata object. It needs to be a valid fully qualified path.
This works fine for me.
public class FileData{
public int id;
public string fname;
}
void Main()
{
List<FileData> list = new List<FileData>{
new FileData { id=1, fname="C:\\install.res.1042.dll"},
new FileData { id=2, fname="C:\\install.res.1041.dll" },
new FileData { id=3, fname="C:\\install.res.9999.dll"}
};
string[] FolderFiles = System.IO.Directory.GetFiles("C:\\");
var results = list
.Where(fd =>
FolderFiles.Any(x=>Path.GetFileNameWithoutExtension(x) ==
Path.GetFileNameWithoutExtension(fd.fname)));
Console.WriteLine(results);
}

If you need to find the difference this should work. This is available via Enumerable.Except.
var dbFiles = ReadList(sqlFiles);
var dbFilePaths =
dbFiles.Select(fdate =>
Path.GetFileNameWithoutExtension(fdate.fname).ToLower());
var fsFilePaths =
Directory
.GetFiles(path2Copy)
.Select(filePath =>
Path.GetFileNameWithoutExtension(filePath).ToLower());
var diff =
dbFilePaths
.Except(fsFilePaths)
.Join(dbFiles,
filePath => filePath,
fdate => fdate.fname,
(filePath, fdate) => fdate)
.ToList();

Related

LINQ-TO-SQL query not working with CSV file

I'm reading a simple csv file from my program. Here's what my csv file looks like:
NASDQ,O,
OTC,O,
NYSE,N,
TSE,T,
Here's my code to read the csv file:
string csvFile = #"x:\tech\SQL_IntlPricing\ExchangeLookup.csv";
string[] csvLines = File.ReadAllLines(csvFile);
var csvValues = csvLines
.Select(l => new {
Exchange = l.Split(',').First(),
Lookup = l.Split(',').Skip(1).First ()});
So far, everything is fine with the code. I'm using the following LINQ query:
from comp in Companies
where !comp.Coverage_status.Contains("drop")
select new
{
FSTick = string.Format("{0}-{1}", comp.Ticker,
csvValues
.Where(v => v.Exchange.Contains(comp.Exchange))
.Select(v => v.Lookup).FirstOrDefault())
};
But I'm getting the following error:
NotSupportedException: Local sequence cannot be used in LINQ to SQL implementations of query operators except the Contains operator.
Basically, I'm trying to get the following results:
AAPL-O
MSFT-O
Is there a way for me to achieve the results I want using my LINQ query?
If Companies are not a lot, then the simple solution would be:
from comp in Companies.Where(c => !c.Coverage_status.Contains("drop")).AsEnumerable()
select new
{
FSTick = string.Format("{0}-{1}", comp.Ticker,
csvValues
.Where(v => v.Exchange.Contains(comp.Exchange))
.Select(v => v.Lookup).FirstOrDefault())
};
Otherwise you could do the filtering there like;
from comp in Companies.Where( c =>
csvValues.Select(cs => cs.Exchange).Contains(comp.Exchange) &&
!c.Coverage_status.Contains("drop")
).AsEnumerable()
select new
{
FSTick = string.Format("{0}-{1}", comp.Ticker,
csvValues
.Where(v => v.Exchange.Contains(comp.Exchange))
.Select(v => v.Lookup).FirstOrDefault())
};
Following my comment above, if converting the linq-sql expression into its extension methods syntax form is ok, you could do the following:
I created a list of companies just for the sake of the example. Company was defined as
public class Company
{
public string Coverage_status { get; set; }
public string Exchange { get; set; }
public string Ticker { get; set; }
}
Here's a full sample of how the code will would look like:
List<string> csvLines = new List<string>
{
"NASDQ,O,",
"OTC,O,",
"NYSE,N,",
"TSE,T,"
};
var csvValues = csvLines
.Select(l => new
{
Exchange = l.Split(',').First(),
Lookup = l.Split(',').Skip(1).First()
});
List<Company> companies = new List<Company>
{
new Company { Coverage_status = "aaa", Ticker = "123", Exchange = "NASDQ"},
new Company { Coverage_status = "1521drop422", Ticker = "1251223", Exchange = "aaaaaaaa"},
new Company { Coverage_status = "f2hdjjd", Ticker = "15525221123", Exchange = "TSE"}
};
var result = companies
.Where(c => !c.Coverage_status.Contains("drop"))
.Select(n => new
{
FSTick = string.Format("{0}-{1}", n.Ticker,
csvValues
.Where(v => v.Exchange.Contains(n.Exchange))
.Select(v => v.Lookup).FirstOrDefault())
});
foreach (var r in result)
Console.WriteLine(r.FSTick);
For the record, this code is definitely not performance-wise.
Output:

RavenDB Collection "in" Collection query

I need to preform a query that check if a collection is in given collection, just like the regular in operation but for collections.
class Post
{
public string[] Tags {get;set;}
}
session.Queury<Post>.Where(x=>x.Tags.in(new[]{".net","c#","RavenDB"})).ToList();
so if i have in my DB:
new Post{Tags= new[]{"C#",".net"}};
it will be returned
but if i have:
new Post{Tags= new[]{"C#",".net","SQLServer"}};
it will not be returned.
Update:
what i am trying to do is this:
session.Query<Post>()
.Where(x => x.Tags.All(y => y.In(new[] { "C#", ".net", "RavenDB" })))
.ToList();
but i got System.NotSupportedException.
I manage to find a solution:
static void Main(string[] args)
{
var sessionStore = new EmbeddableDocumentStore
{
RunInMemory = true,
UseEmbeddedHttpServer = true,
Conventions =
{
DefaultQueryingConsistency = ConsistencyOptions.AlwaysWaitForNonStaleResultsAsOfLastWrite
}
};
sessionStore.Initialize();
using (var session = sessionStore.OpenSession())
{
var allTags = new[] {"C#", ".net", "RavenDB", "Linux", "Mac"};
var tagsCollection = new[] {"C#", ".net", "RavenDB"};
var complementTagsCollection = allTags.Except(tagsCollection).ToList();
session.Store(new Post
{
Tags = new List<string>{"C#",".net"}
});
session.SaveChanges();
// Posts where all their tags are in tagsCollection
var result = session.Query<Post>().Where(x => !x.Tags.In(complementTagsCollection)).ToList();
}
}
The way IN works, it matches ANY of them.
If you want to match all you have to do a separate check for each.

Efficiently retrieving and filtering files by using filename

i am a newbie hier, i try to retreive files by using filenames, which have the following definition:
Items number + Revision + lot number.pdf
For example:
1109093-A2 (85806S).pdf
1109093-A3 (85806S).pdf
1109092-A1 (85806S).pdf
1109092-A2 (85806S).pdf
for this sample file: 1109093-A2 (85806S).pdf
Items number: 1109093
Revision: -A2
End item number: (85806S)
for my search result, i am supose to have only this files.
1109093-A3 (85806S).pdf
1109092-A2 (85806S).pdf
i must have only files, with the actual Revision like the one up there( A3 ,A2).
But it not, still now i am getting all Files, how can i sort it by Revision please???
A1, A2, A3, A.... (Revisions) represents the selection criteria I should use. I wrote the follow function for this job.
private string[] GetFiles()
{
strSourcePath = textBox1.Text;
strTargetPath = textBox2.Text;
string fileName = string.Empty;
strExtension = "*).pdf";
string[] files = null;
if (Directory.Exists(strSourcePath))
{
files = Directory.GetFiles(strSourcePath, strExtension, SearchOption.AllDirectories);
var Result = "";
string joined = String.Join("# ", Result);
files = null;
Result = joined.Split('#');
files = Result.Where(file => Regex.IsMatch(Path.GetFileName(file), "^[0-9]+")).ToArray();
}
else
{
MessageBox.Show("Source path does not exist!");
}
return files ;
}
After you got the paths, you can parse the filename, extract revision/etc and sort based on your criteria.
This code parse as an anonymous class (for readability) and sort based on ItemNumber, Revision.
The anonymous class contains the path and item number/revision/end number info.
See the demo for complete example
var paths = new [] {
"1109093-A2 (85806S).pdf",
"1109093-A3 (85806S).pdf",
"1109092-A1 (85806S).pdf",
"1109092-A2 (85806S).pdf",
};
var result = paths.Select(x => {
var match = Regex.Match(x, #"(?<ItemsNumber>\d+)-(?<Revision>\w+)\s+\((?<EndItemNumber>\w+)\).pdf");
if (match.Success)
{
return new { ItemNumber = match.Groups[1].Value, Revision = match.Groups[2].Value, EndItemNumber = match.Groups[3].Value, Path = x };
}
else {
return new { ItemNumber = "", Revision = "", EndItemNumber = "", Path = x };
}
})
.OrderBy(x => x.ItemNumber).ThenBy(x => x.Revision);
demo: https://dotnetfiddle.net/47uZni
Using your template I wrote this function, but the return value is always the same - one item, but not a list as I expected. I do not know why. Did you have some idea?
private string[] SortFileName(string []TemP)
{
var paths = GetTheFileName(TemP);
List<string> TheCollection = new List<string>();
var result = paths.Select(x => {
var match = Regex.Match(x, #"(?<ItemsNumber>\d+)-(?<Revision>\w+)\s+\((?<EndItemNumber>\w+)\).pdf");
if (match.Success)
{
return new { ItemNumber = match.Groups[1].Value, Revision = match.Groups[2].Value, EndItemNumber = match.Groups[3].Value, Path = x };
}
else {
return new { ItemNumber = "", Revision = "", EndItemNumber = "", Path = x };
}
})
.GroupBy(x => x.ItemNumber)
.Select(x => x.OrderByDescending(y => y.Revision).First());
foreach (var item in result)
{
TheCollection.Add(item.Path.ToString());
}
return TheCollection.ToArray();
}
PS: GetTheFileName(TemP); return an array with more than 130 items. thanks for the coming help.

MongoDB select row by id and get fields (in c#) [duplicate]

first time i'm using MongoDB.
I have read this example:
SELECT a,b FROM users WHERE age=33
db.users.find({age:33}, {a:1,b:1})
But I can't translate it into C#. Can anyone help me?
I have translated your query below using the new C# driver (2.2)
var mongoClient = new MongoClient(""mongodb://127.0.0.1:27017"");
var database = mongoClient.GetDatabase("databaseName");
IMongoCollection<Users> _collection = database.GetCollection<Users>("Users");
var condition = Builders<Users>.Filter.Eq(p => p.age, 33);
var fields = Builders<Users>.Projection.Include(p => p.a).Include(p => p.b);
var results= _collection.Find(condition).Project<Users>(fields).ToList().AsQueryable();
You can do it using SetFields method of MongoCursor class, below full example:
var server = MongoServer.Create(connectionString);
var db = _server.GetDatabase("dbName");
var users = db.GetCollection("users");
var cursor = users.FindAs<DocType>(Query.EQ("age", 33));
cursor.SetFields(Fields.Include("a", "b"));
var items = cursor.ToList();
you can use anonymous class
public class User
{
public int age;
public string a;
public string b;
}
var collection = db.GetCollection<User>("Users");
var results = collection.Find(Builders<User>.Filter.Eq(user => user.age, 33))
.Project(u => new { u.a, u.b }).ToList();
//create user class
//(not sure how your class looks like)
public class User
{
public int age;
public string a;
public string b;
}
//then you can use LINQ easily
var server = MongoServer.Create(connectionString);
var db = server.GetDatabase("dbName");
var usersCollection = db.GetCollection<User>("users");
var filteredCollection = usersCollection.AsQueryable().Where(x=> x.age < 33).Where(x=> x.a != null).Contains(x=> x.b != null);

Linq query only returning first item of array

Let the string projects equal "p1,p2,p3" and in the database the identifier for each exists as follows p1 = 1 ,p2 = 2, p3 = 3. Only the first project in the list is being returned in my query, any thoughts on why?
private List<int> getProjects(string projects)
{
String[] projectArray = projects.Split(',');
QMOIIEntities db = new QMOIIEntities();
var projectList = db.wbs_projects
.Where(x => projectArray.Contains(x.prjName))
.Select(x => x.prjID).ToList();
return projectList;
}
**UPDATE
This issue was whitespace in the string I changed
String[] projectArray = projects.Split(',');
to
String[] projectArray = projects.Trim().Split(',');
The following code uses the same logic, the one you have mentioned in your question. I have created dummy data. The code is behaving as expected i.e. the output is the prjID corresponding to each prjName.
void Main()
{
string projects = "p1,p2,p3";
List<string> projectArray = projects.Split(',').ToList();
TestEntities db = new TestEntities();
db.wbs_projects = new List<TestEntities>();
db.wbs_projects.Add(new TestEntities(){prjName = "p1",prjID="Test1"});
db.wbs_projects.Add(new TestEntities(){prjName = "p2",prjID="Test2"});
db.wbs_projects.Add(new TestEntities(){prjName = "p3",prjID="Test3"});
var projectList = db.wbs_projects
.Where(x => projectArray.Contains(x.prjName))
.Select(x => x.prjID).ToList();
foreach(var item in projectList)
{
Console.WriteLine(item);//Test1,Test2,Test3
}
}
public class TestEntities
{
public List<TestEntities> wbs_projects{get;set;}
public string prjName{get;set;}
public string prjID{get;set;}
}

Categories