List<String>

S

shapper

Hello,

I have been coding a lot with Linq but I got stopped by something
unexpected.

I have a IList<String> that contains values from 1 to 10. An example:

IList<String> roles = (new String[] { "1", "2", "4",
"10" }).ToList();
String role = "5";

1) roles never have repeated values.
2) roles have only one value between 4 to 7. Example:

roles can contain "1", "2" "5" and "10"
but it can't contain "1" "2", "4", "7" and "10"

Basically role has a value that should update the value in roles
between 4 and 7.
So in the example posted: "5" will be added to roles and "4" will be
removed.

I was trying to use something like:

roles.Remove(s => Int32.Parse(s) >= 4 && Int32.Parse(s) <= 7);
roles.Add(role);

But Remove does not allow this ...

How can I do this?

Thanks,
Miiguel
 
P

Peter Duniho

[...]
Basically role has a value that should update the value in roles
between 4 and 7.
So in the example posted: "5" will be added to roles and "4" will be
removed.

I was trying to use something like:

roles.Remove(s => Int32.Parse(s) >= 4 && Int32.Parse(s) <= 7);
roles.Add(role);

But Remove does not allow this ...

How can I do this?

Can you use List<T> instead of IList<T>? If so, there's a RemoveAll()
method.

Alternatively, it should not be all that bad to just write:

int irole = 0;
while (irole < roles.Count)
{
int roleCur = int.Parse(roles[irole]);

if (roleCur >= 4 && roleCur <= 7)
{
roles.RemoveAt(irole);
}
else
{
irole++;
}
}

Put that in a utility method somewhere to keep the code neat.

You could also use the Enumerable.Range() and Enumerable.Except() methods,
but IMHO that'd be overkill in a large way. It'd require not only the
dynamic creation of a bunch of strings (or the caching of the results of
that), but the instantiation of a whole new IList<String> object to
replace the original (since LINQ is about returning new enumerations, not
modifying existing ones).

Pete
 
P

Patrice

Or for (int i = 4; i <= 7; i++) roles.Remove(i.ToString());

You are just expecting to see lambads everywhere because of Linq ;-)

Note also that the code above is not perfectly correct. Not sure about why
you use string when it seems you are using numeric values. Hopefully you
have double checked this but it could have of course adverse effects. For
example if you have "51" in your list, do want it to be deleted because the
string "51" is between "4" and "7" ?
 
S

shapper

[...]
Basically role has a value that should update the value in roles
between 4 and 7.
So in the example posted: "5" will be added to roles and "4" will be
removed.
I was trying to use something like:
roles.Remove(s => Int32.Parse(s) >= 4 && Int32.Parse(s) <= 7);
roles.Add(role);
But Remove does not allow this ...
How can I do this?

Can you use List<T> instead of IList<T>?  If so, there's a RemoveAll()  
method.

Alternatively, it should not be all that bad to just write:

     int irole = 0;
     while (irole < roles.Count)
     {
         int roleCur = int.Parse(roles[irole]);

         if (roleCur >= 4 && roleCur <= 7)
         {
             roles.RemoveAt(irole);
         }
         else
         {
             irole++;
         }
     }

Put that in a utility method somewhere to keep the code neat.

You could also use the Enumerable.Range() and Enumerable.Except() methods,  
but IMHO that'd be overkill in a large way.  It'd require not only the  
dynamic creation of a bunch of strings (or the caching of the results of  
that), but the instantiation of a whole new IList<String> object to  
replace the original (since LINQ is about returning new enumerations, not 
modifying existing ones).

Pete

Thank You Pete
 
S

shapper

Or for (int i = 4; i <= 7; i++) roles.Remove(i.ToString());

You are just expecting to see lambads everywhere because of Linq ;-)

Yes it is true ... When working with data from database I always tend
to use lambdas.
I don't even use "normal" queries anymore ...
I got used to it ...
And sometimes I even forget the for loop ...
Not sure about why you use string when it seems you are using numeric values. Hopefully you
have double checked this but it could have of course adverse effects. For
example if you have "51" in your list, do want it to be deleted because the
string "51" is between "4" and "7" ?

No. But I am parsing to Int before I compare it.
The reason why I use String is because this comes from a ViewModel
that is filled in a MVC View Form.

On my FluentValidation I need to check if any value(s) were selected,
for example in a DropDownList or MultiDropDownList.

The validation checks for empty in Strings ...

I am not completely convinced about using String in this case yet ...
But first I needed to have this work and now try to see what happens
with Ints.
On the first try didn't work to well.

Thank You,
Miguel
 
P

Peter Duniho

[...]
The reason why I use String is because this comes from a ViewModel
that is filled in a MVC View Form.

For what it's worth...

I don't know much at all about the .NET MVC libraries. But I find it
strange you might have anything called "ViewModel". The whole point of
the MVC design pattern is that the view and model are two different things.

In the conventional paradigm, the model would define the data format. If
an int was the most natural format, that's what you'd use. The controller
and/or view would be responsible for converting from the string used in
the display to the int being used in the model.

Given a requirement to mix ints and strings, IMHO it is better to parse a
string than to format an int, because the parsing doesn't create a new
object, while the formatting does. Comparing ints can be more efficient
than comparing strings too. But ideally, you wouldn't have to do either,
at least not in the model object itself where your business logic resides.

Pete
 
S

shapper

I don't know much at all about the .NET MVC libraries.  But I find it  
strange you might have anything called "ViewModel".  The whole point of 
the MVC design pattern is that the view and model are two different things.

In the conventional paradigm, the model would define the data format.  If  
an int was the most natural format, that's what you'd use.  The controller  
and/or view would be responsible for converting from the string used in  
the display to the int being used in the model.

Models in ASP.NET MVC is a really tricky problem and I have been
testing very options ...

Basically this is what I do:

I have the domain model which is mapped from the database using Entity
Framework, Linq To SQL, NHibernate, etc.

My projects are organized as follows:

Pj.Infrastructure (Common code to all layers. Helpers, etc)
Pj.Domain (Entities, Repositories and Services)
Pj.Application (Services like TwitterService, MailService, etc)
Pj.Presentation (MVC project)

I use the 1 "ViewModel" - 1 "View".
(It simplifies a LOT when using complex data relation and forms)

Then I have AutoMapper to in the controller map between Domain
Entities and View Models.
The View Models are flattered and completely adapted to the View
requirements.
The validators validate these View Models on form submission.
If the view model is valid the controller Maps it to an Entity and
sends it to Services or Repositories.

In Domain I might use only repositories returning Entities or
sometimes I use Services over the repositories which kind of change
the form of the Entity (Flatering, etc) to make it easier for
AutoMapper on the Controller.

This is an area where I have been trying a lot of options but this one
is the more flexible that allows me to have all complex forms and have
separation between Entities and the "View Models" delivered to the
Views.

I call it View Models so in MVC forums it is easier to understand what
I am talking about.

Is this what you meant?

Thanks,
Miguel
 
P

Peter Duniho

[...]
I use the 1 "ViewModel" - 1 "View".

That sentence is meaningless to me. I understood every word through "I
use the". Everything after that made no sense.
(It simplifies a LOT when using complex data relation and forms)

Then I have AutoMapper to in the controller map between Domain
Entities and View Models.

What's a "View Model"? Is it a view? Or a model? Or both? If not both,
why is the word that it's not part of the name?
The View Models are flattered and completely adapted to the View
requirements.

You are make kind, complimentary statements about your "View Models"?
What "View requirements" require any adaptation, and in what way are "View
Models" adapted in that way? If they need to be adapted, why would they
NOT be "completely adapted"? Is it legal to be only partially "adapted to
the View requirements"?
The validators validate these View Models on form submission.
If the view model is valid the controller Maps it to an Entity and
sends it to Services or Repositories.

See above. The term "View Model" doesn't make any sense to me.
[...]
I call it View Models so in MVC forums it is easier to understand what
I am talking about.

Is this what you meant?

Honestly, most of your attempt of a description still makes no sense to
me. More importantly, this is not an MVC forum. Perhaps the
contradictory term "View Model" has some specific meaning someone in an
ASP.NET MVC forum would understand, but to people who are simply familiar
with the general design pattern named "model-view-controller", the idea of
a single object that is both "view" and "model" is antithetical to the
fundamental idea of the MVC design pattern. And naming an object
"ViewModel" that is not both a "view" and a "model" is just bad naming.
So either you've just got a bad name, or your code doesn't fit the usual
idea of MVC.

The naming question may or may not be an important point, frankly. If
it's just a bad name, fine. We can ignore that point for now.

The main point of my reply was to point out that if your model uses
integers to identify roles, then the fact that strings are used in the
view is unimportant and irrelevant. Validation and state manipulation
(such as adding a specific role that replaces any role within the range of
values 4-7) that is not part of the presentation (i.e. the view) is
necessarily handled in the model, which (by the above assumption) uses
integers.

The whole point of MVC is to provide a well-defined boundary between
objects that maintain the fundamental state of the data the user is
manipulating (the model), and those objects that actually allow the user
to manipulate that state (the view). If you find yourself doing
model-specific operations (i.e. manipulating integers) in the domain of
the view's data format (i.e. strings), there's something wrong.

Pete
 
G

Göran Andersson

shapper said:
Hello,

I have been coding a lot with Linq but I got stopped by something
unexpected.

I have a IList<String> that contains values from 1 to 10. An example:

IList<String> roles = (new String[] { "1", "2", "4",
"10" }).ToList();
String role = "5";

1) roles never have repeated values.
2) roles have only one value between 4 to 7. Example:

roles can contain "1", "2" "5" and "10"
but it can't contain "1" "2", "4", "7" and "10"

Basically role has a value that should update the value in roles
between 4 and 7.
So in the example posted: "5" will be added to roles and "4" will be
removed.

I was trying to use something like:

roles.Remove(s => Int32.Parse(s) >= 4 && Int32.Parse(s) <= 7);
roles.Add(role);

But Remove does not allow this ...

How can I do this?

Thanks,
Miiguel

Use a List<string> instead of IList<string>, and you can do:

roles.RemoveAll(s => Int32.Parse(s) >= 4 && Int32.Parse(s) <= 7);
 
S

shapper

What's a "View Model"?  Is it a view?  Or a model?  Or both?  If not both,  
why is the word that it's not part of the name?

It is a model specially "prepared" to be sent to a view.
You are make kind, complimentary statements about your "View Models"?  
What "View requirements" require any adaptation, and in what way are "View  
Models" adapted in that way?  If they need to be adapted, why would they  
NOT be "completely adapted"?  Is it legal to be only partially "adaptedto  
the View requirements"?

Yes, you can have a PostCreate and PostEdit views with some
differences in data and in validation.
Both have different models and different validators ...

Can I create a common model for both? Yes, I can and I do but only in
same cases when it is possible.

In fact I use something like this:

public class PostForm { // Porperties }

public class PostCreate : PostForm {}

public class PostEdit : PostForm {}

Now I can have two views: Post/Create and Post/Edit that use a common
form.
Yet having two different validators: PostCreateValidator and
PostEditValidator.

Bu I can also have 2 forms and 2 validators ..
Or 1 form and 1 validator: PostFormValidator.

However in the end both must be mapped to the same entity.
The term "View Model" doesn't make any sense to me.

Honestly, most of your attempt of a description still makes no sense to  
me.  More importantly, this is not an MVC forum.  Perhaps the  
contradictory term "View Model" has some specific meaning someone in an  
ASP.NET MVC forum would understand, but to people who are simply familiar 
with the general design pattern named "model-view-controller", the idea of  
a single object that is both "view" and "model" is antithetical to the  
fundamental idea of the MVC design pattern.  And naming an object  
"ViewModel" that is not both a "view" and a "model" is just bad naming.  
So either you've just got a bad name, or your code doesn't fit the usual  
idea of MVC.

The naming question may or may not be an important point, frankly.  If  
it's just a bad name, fine.  We can ignore that point for now.

The ViewModel is really how the models sent by the controllers to the
views are named.
The link Tom posted is really good explaining that.
I know this is not a model but I wrote ViewModel as I am so used to
writing that ...
.... But I will try to remember to write only model.
The main point of my reply was to point out that if your model uses  
integers to identify roles, then the fact that strings are used in the  
view is unimportant and irrelevant.  Validation and state manipulation  
(such as adding a specific role that replaces any role within the range of  
values 4-7) that is not part of the presentation (i.e. the view) is  
necessarily handled in the model, which (by the above assumption) uses  
integers.

I do all validation before sending to the domain.
There will never be invalid entities in the domain.
Everything is taken care before.
The whole point of MVC is to provide a well-defined boundary between  
objects that maintain the fundamental state of the data the user is  
manipulating (the model), and those objects that actually allow the user  
to manipulate that state (the view).  If you find yourself doing  
model-specific operations (i.e. manipulating integers) in the domain of  
the view's data format (i.e. strings), there's something wrong.

Again, since the "ViewModels" contain some of the data of one or more
entities flattered and ready for the view then it makes sense that
sometimes the data is not exactly in the same format.
But when sent to the model it will be validated and mapped back to an
entity.

Thank You,
Miguel
 
S

shapper

Use a List<string> instead of IList<string>, and you can do:

roles.RemoveAll(s => Int32.Parse(s) >= 4 && Int32.Parse(s) <= 7);

Got it ...

But when using a Model (Class) where it has a collection property
which only function would be to be looped to display its values
shouldn't I use IList?

I usually use IList just for the case I need to apply some extra
filtering ...

.... And IEnumerable in other cases ...

But probably I am wrong on this.

Thanks,
Miguel
 
G

Göran Andersson

shapper said:
Got it ...

But when using a Model (Class) where it has a collection property
which only function would be to be looped to display its values
shouldn't I use IList?

I usually use IList just for the case I need to apply some extra
filtering ...

... And IEnumerable in other cases ...

But probably I am wrong on this.

Thanks,
Miguel

If you only want to be able to read from the collection, you should use
IEnumerable<T>. If you use IList<T> you are not limiting the access
much, so you can just as well expose the List<T> class to give full
access to the collection. The only reason to expose IList<T> instead of
List<T> would be if you think that you need to change the type of the
underlying collection to some other type that implements IList<T>.

If you want to get an altered result without changing the original
collection, you use LINQ (or extension methods to be picky, as this is
not really LINQ):

IEnumerable<string> filtered =
roles
.Where(r => Int32.Parse(r) >= 4 && Int32.Parse(r) <= 7)
.Concat(
new string[] { role }
);

This will create an expression that returns a collection where the
existing role between "4" and "7" is replaced with the new role, but the
roles collection is unchanged.
 

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