Globarlly use var (from linq) or anything equivalent ?

R

Rich P

"files" here is a List<string> object. I retrieve a list of filenames
and then group them alphabetically -- like AA1, AA2, AA3, the AA group
has 3 files, then BB1, BB2, BB3, BB4 contains 4 files in the BB group,
... using the linq below.
files = new List<string>(GetMyFiles(strPath));
char[] rgchDigits = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9'
};

var grouped = from file in files
let name = Path.GetFileName(file)
group file by name.Substring(0, name.IndexOfAny(rgchDigits));

foreach (var group in grouped)
Console.WriteLine(group.Key + " " + group.Count().ToString();

<<

Instead of using "var grouped = ... " locally inside a procedure, I
would like to populate a similar object that I can use globally. Here
is what I am trying to do: I retrieve a list of fileNames into files.
I then loop through files and display each fileName contained in files
on a label on a winform. The "var grouped = ... " list contains
information as follows:

AA 3
BB 4
CC 2
DD 7

The fileNames in files are groups of fileNames that contain the same
characters onto which I append a number. AA1, AA2, ... DD1, DD2,
...DD127, ...

As I loop through files -- I display the fileNames in the AA group and I
want to display the group count of files that contain AA alongside.
Then the BB's, ...

Theorectically I would have a table like this

Name Group Count
AA1 AA 3
AA2 AA 3
AA3 AA 3
BB1 BB 4
BB2 BB 4
BB3 BB 4
BB4 BB 4
CC1 CC 15
... CC 15
CC15 CC 15
...

I want to display the individual fileNames and the group count from a
loop. One thought would be to populate an ADO.Net table with the
contents of "files" and "grouped" and loop through the table. But that
seems a little redundant. One challenge I am also seeing is to
correctly line up "files" with "grouped" so that the AAs counts don't
get mixed with HH counts for example.

On a real redundant note -- I could write the contents of "files" to a
sql server #temp table, parse out the characters of the filenames (to
the "group" column), then do a group by query and read all that back to
my ADO.net table. The downside of this idea is that I have thousands of
filenames to process (could take a while) and this adds a dependency on
a sql server.

Would a Dictionary fit into this scenario? How to implement?

Any suggestions would be appreciated how I could perform this operation
without introducy unnecessary redundancies and external dependencies.

Thanks,

Rich
 
R

Rich P

I decided to go with the ADO.Net table idea. Here is what that looks
like:

private void LinqOrganize()
{
char[] rgchDigits = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9'
};

var grouped = from file in files
let name = Path.GetFileName(file)
group file by name.Substring(0, name.IndexOfAny(rgchDigits));

DataRow dr;
int j = 0;
int cnt = ds1.tblFiles.Rows.Count;
foreach (var group in grouped)
{
for (int i = j; i < cnt; i++)
{
j = i;
dr = ds1.tblFiles.Rows;
if (dr[0].ToString().Contains(group.Key.ToString()).Equals(true))
{
dr[1] = group.Key.ToString();
dr[2] = group.Count();
}
else
break;
}
}
}

After reading the files into "files" I then populate my ADO.Net table
(the redundant part) ds1.tblFiles. This table contains 4 columns --
FileName, GroupName, GroupCount, rowID (key field). Then I call
LinqOrganize() to perform the groupings and add the results to
ds1.tblFiles. This seems to work great on a small set of files, but I
will see how it works with 14,000+ files.

And thanks to all who have helped me out with the linq code.

Rich
 
M

Mr. Arnold

Rich said:
"files" here is a List<string> object. I retrieve a list of filenames
and then group them alphabetically -- like AA1, AA2, AA3, the AA group
has 3 files, then BB1, BB2, BB3, BB4 contains 4 files in the BB group,
.. using the linq below.

files = new List<string>(GetMyFiles(strPath));
char[] rgchDigits = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9'
};

var grouped = from file in files
let name = Path.GetFileName(file)
group file by name.Substring(0, name.IndexOfAny(rgchDigits));

foreach (var group in grouped)
Console.WriteLine(group.Key + " " + group.Count().ToString();

<<

Instead of using "var grouped = ... " locally inside a procedure, I
would like to populate a similar object that I can use globally. Here
is what I am trying to do: I retrieve a list of fileNames into files.
I then loop through files and display each fileName contained in files
on a label on a winform. The "var grouped = ... " list contains
information as follows:

AA 3
BB 4
CC 2
DD 7

private List<group> grouped = new List<groups>(); at the top of the
Class, then any method in the class can see grouped and you don't need
the var.
The fileNames in files are groups of fileNames that contain the same
characters onto which I append a number. AA1, AA2, ... DD1, DD2,
..DD127, ...

As I loop through files -- I display the fileNames in the AA group and I
want to display the group count of files that contain AA alongside.
Then the BB's, ...

Theorectically I would have a table like this

Name Group Count
AA1 AA 3
AA2 AA 3
AA3 AA 3
BB1 BB 4
BB2 BB 4
BB3 BB 4
BB4 BB 4
CC1 CC 15
.. CC 15
CC15 CC 15
..

I want to display the individual fileNames and the group count from a
loop. One thought would be to populate an ADO.Net table with the
contents of "files" and "grouped" and loop through the table. But that
seems a little redundant. One challenge I am also seeing is to
correctly line up "files" with "grouped" so that the AAs counts don't
get mixed with HH counts for example.

Why would you not use an object that has public accessor properties? You
can call it group.

On a real redundant note -- I could write the contents of "files" to a
sql server #temp table, parse out the characters of the filenames (to
the "group" column), then do a group by query and read all that back to
my ADO.net table. The downside of this idea is that I have thousands of
filenames to process (could take a while) and this adds a dependency on
a sql server.

You're going to have to loop on something after you populate the object
on initial load and loading it to the List<T>. So loop on the List<T>
and go get the count for AA using Linq query and populate Count property
in the object.

I have never done a loop on a collection with a foreach and queried the
same collection for count based on a object's properties in the
collection while in the loop. But I don't see why that would work. :)
You would do one query for each group and not query for a count again
for the same group in the object in the collection.

So, why can't you use an object, write a collection of objects and hold
them in memory? Why do you need to use SQL server. You hit SQL server
one time and not go back.

You're talking Linq so learn how to use Linq to do what you're doing
instead trying to go back to SQL Server using a table.

It's all right there in front of you in memory if you use a List<T>.
 
G

Göran Andersson

Rich said:
"files" here is a List<string> object. I retrieve a list of filenames
and then group them alphabetically -- like AA1, AA2, AA3, the AA group
has 3 files, then BB1, BB2, BB3, BB4 contains 4 files in the BB group,
.. using the linq below.

files = new List<string>(GetMyFiles(strPath));
char[] rgchDigits = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9'
};

var grouped = from file in files
let name = Path.GetFileName(file)
group file by name.Substring(0, name.IndexOfAny(rgchDigits));

foreach (var group in grouped)
Console.WriteLine(group.Key + " " + group.Count().ToString();

<<

Instead of using "var grouped = ... " locally inside a procedure, I
would like to populate a similar object that I can use globally. Here
is what I am trying to do: I retrieve a list of fileNames into files.
I then loop through files and display each fileName contained in files
on a label on a winform. The "var grouped = ... " list contains
information as follows:

AA 3
BB 4
CC 2
DD 7

The fileNames in files are groups of fileNames that contain the same
characters onto which I append a number. AA1, AA2, ... DD1, DD2,
..DD127, ...

As I loop through files -- I display the fileNames in the AA group and I
want to display the group count of files that contain AA alongside.
Then the BB's, ...

Theorectically I would have a table like this

Name Group Count
AA1 AA 3
AA2 AA 3
AA3 AA 3
BB1 BB 4
BB2 BB 4
BB3 BB 4
BB4 BB 4
CC1 CC 15
.. CC 15
CC15 CC 15
..

I want to display the individual fileNames and the group count from a
loop. One thought would be to populate an ADO.Net table with the
contents of "files" and "grouped" and loop through the table. But that
seems a little redundant. One challenge I am also seeing is to
correctly line up "files" with "grouped" so that the AAs counts don't
get mixed with HH counts for example.

On a real redundant note -- I could write the contents of "files" to a
sql server #temp table, parse out the characters of the filenames (to
the "group" column), then do a group by query and read all that back to
my ADO.net table. The downside of this idea is that I have thousands of
filenames to process (could take a while) and this adds a dependency on
a sql server.

Would a Dictionary fit into this scenario? How to implement?

Any suggestions would be appreciated how I could perform this operation
without introducy unnecessary redundancies and external dependencies.

Thanks,

Rich

You can easily put the group names and counts in a dictionary:

Dictionary<string, int> grouped = (
from file in files
let name = Path.GetFileName(file)
group file by name.Substring(0, name.IndexOfAny(rgchDigits))
).ToDictionary(g => g.Key, g => g.Count);

As you can find out the group from the file name, you can get the group
information for each file:

foreach (string file in files) {
string name = Path.GetFileName(file);
string group = name.Substring(0, name.IndexOfAny(rgchDigits));
int count = grouped[group];
Console.WriteLine("{0}, {1}, {2}", name, group, count);
}
 
R

Rich P

Thank you for your reply and for the weblink. Very cool suggestion --
I'm glad that I posted this.
Why would you not use an object that has public accessor properties? You
can call it group.

<http://www.c-sharpcorner.com/UploadFile/rajeshvs/PropertiesInCS11122005
001040AM/PropertiesInCS.aspx>
<<

I ran into a couple of problems -- with the Linq portion of my procedure
(which I will describe below). And if I understand the suggestion
correctly -- I will create a class called Grouped and then create a list
based on this class and populate that list from my Linq Query? Nice. I
am definitely going to give that a whirl. Here is what I am thinking --
please correct me if I am proceeding the wrong way about this:
//the original linq query
char[] rgchDigits = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9'
};

var grouped = from file in files
let name = Path.GetFileName(file)
group file by name.Substring(0, name.IndexOfAny(rgchDigits));
<<

List<Grouped> grouped = from file in files ...

Here is my sample class. How to mix this into the linq query?

class Grouped
{
private string sNam;
private int iCnt;

public string fName
{
get
{
return sNam;
}
set
{
sNam = value;
}
}

public string gName
{
get
{
return sNam;
}
set
{
sNam = value;
}
}

public int iCount
{
get
{
return iCnt;
}
set
{
iCnt = value;
}
}
}


Here is one problem I ran into with the Linq Query -- casing: AAa1.jpg,
AAA2.bmp, aaA3.gif, bbb1.jpg, BBb2.jpg, BBB3.bmp, bBB4.gif, ... How can
I modify the linq query to disregard casing?

And the other problem I ran into was this:

aAA1.jpg, AAa2.bmp, AAA3.gif, bbB1.jpg, bbB.jpg, bBB3.bmp, BBB4.gif, ...

some of the filenames were missing digits at the end of the file name.
Now I need to write another linq query to extract the filenames which
don't have digits (so I can correct them). Here is my pseudocode:

char[] rgchDigits = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9'
};

var grouped = from file NOT in files
let name = Path.GetFileName(file)
group file by name.Substring(0, name.IndexOfAny(rgchDigits));

How can I exclude the filenames that DO have digits?

Thanks,

Rich
 
M

Mr. Arnold

Rich said:
Thank you for your reply and for the weblink. Very cool suggestion --
I'm glad that I posted this.

Why would you not use an object that has public accessor properties? You
can call it group.

<http://www.c-sharpcorner.com/UploadFile/rajeshvs/PropertiesInCS11122005
001040AM/PropertiesInCS.aspx>
<<

I ran into a couple of problems -- with the Linq portion of my procedure
(which I will describe below). And if I understand the suggestion
correctly -- I will create a class called Grouped and then create a list
based on this class and populate that list from my Linq Query?

Yes you can do that.
Nice. I
am definitely going to give that a whirl. Here is what I am thinking --
please correct me if I am proceeding the wrong way about this:

//the original linq query
char[] rgchDigits = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9'
};

var grouped = from file in files
let name = Path.GetFileName(file)
group file by name.Substring(0, name.IndexOfAny(rgchDigits));
<<

List<Grouped> grouped = from file in files ...

Here is my sample class. How to mix this into the linq query?

class Grouped
{
private string sNam;
private int iCnt;

public string fName
{
get
{
return sNam;
}
set
{
sNam = value;
}
}

public string gName
{
get
{
return sNam;
}
set
{
sNam = value;
}
}

public int iCount
{
get
{
return iCnt;
}
set
{
iCnt = value;
}
}
}


Here is one problem I ran into with the Linq Query -- casing: AAa1.jpg,
AAA2.bmp, aaA3.gif, bbb1.jpg, BBb2.jpg, BBB3.bmp, bBB4.gif, ... How can
I modify the linq query to disregard casing?

I don't understand what you're talking about here. What's the problem?
And the other problem I ran into was this:

aAA1.jpg, AAa2.bmp, AAA3.gif, bbB1.jpg, bbB.jpg, bBB3.bmp, BBB4.gif, ...

some of the filenames were missing digits at the end of the file name.
Now I need to write another linq query to extract the filenames which
don't have digits (so I can correct them). Here is my pseudocode:

char[] rgchDigits = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9'
};

var grouped = from file NOT in files
let name = Path.GetFileName(file)
group file by name.Substring(0, name.IndexOfAny(rgchDigits));

How can I exclude the filenames that DO have digits?

I suspect you're going to have to have a Where clause on
name.Contains("1").

This is one way you might be able to do it using a Where in the Linq query.

var grouped =(from a in List<T> Where !a.name.contains("1")
|| !a.name.contains("2") select a).Tolist();


The list of || -- (OR) from "0"-"9".
 
R

Rich P

Thanks again for the response.
I suspect you're going to have to have a Where clause on
name.Contains("1").

This is one way you might be able to do it using a Where in the Linq
query.

var grouped =(from a in List<T> Where !a.name.contains("1")
|| !a.name.contains("2") select a).Tolist();


The list of || -- (OR) from "0"-"9".
<<

Here is what I ended up doing: in the procedure that initially pulls
the list I added another list (slightly redundant) where I I do this to
get around the casing problem -- using .ToUpper():

List<string> f1 = new List<string>(GetMyFiles(strPath));
files = f1.Select(p => p.ToUpper());
//--files is a global IEnumerable<string> list

then I perform a linq version of "select case" in the grouping
procedure:

char[] rgchDigits = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9'
};

var grouped = from file in files
let name = Path.GetFileName(file)
group file by (name.IndexOfAny(rgchDigits) > -1 ? name.Substring(0,
name.IndexOfAny(rgchDigits)) : name);


I think (I hope) this is the core of the project and the rest is just
busy work now.


Rich
 
M

Mr. Arnold

Rich said:
Thanks again for the response.

I suspect you're going to have to have a Where clause on
name.Contains("1").

This is one way you might be able to do it using a Where in the Linq
query.

var grouped =(from a in List<T> Where !a.name.contains("1")
|| !a.name.contains("2") select a).Tolist();


The list of || -- (OR) from "0"-"9".
<<

Here is what I ended up doing: in the procedure that initially pulls
the list I added another list (slightly redundant) where I I do this to
get around the casing problem -- using .ToUpper():

List<string> f1 = new List<string>(GetMyFiles(strPath));
files = f1.Select(p => p.ToUpper());
//--files is a global IEnumerable<string> list

then I perform a linq version of "select case" in the grouping
procedure:

char[] rgchDigits = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9'
};

var grouped = from file in files
let name = Path.GetFileName(file)
group file by (name.IndexOfAny(rgchDigits) > -1 ? name.Substring(0,
name.IndexOfAny(rgchDigits)) : name);


I think (I hope) this is the core of the project and the rest is just
busy work now.

I hope it works for you.

You can use auto-properties in a class/object to. It saves you some typing.

public string Name {get; set:}

http://msdn.microsoft.com/en-us/library/bb384054.aspx
 
R

Rich P

I hope it works for you.

You can use auto-properties in a class/object to. It saves you some
typing.

public string Name {get; set:}

http://msdn.microsoft.com/en-us/library/bb384054.aspx
<<

Thanks again, and thanks for the link. I do believe my migration
project is finally underway and running smoothly. Using a class list
List<myCustomClass> files seems more efficient for this project than
using the ADO.Net table.

Rich
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Top