简体   繁体   中英

Grouping and remove from list

I have following type

public class Parameter
{
   public string Name {get;set;}
   public string PathType {get;set;}
}

My parameter list like:

List<Parameter> params = new List<Parameter>();
params.Add(new Parameter{ Name ="A", PathType ="path" });
params.Add(new Parameter{ Name ="B", PathType ="query" });
params.Add(new Parameter{ Name ="C", PathType ="path" });
params.Add(new Parameter{ Name ="C", PathType ="query" });
params.Add(new Parameter{ Name ="D", PathType ="path" });
params.Add(new Parameter{ Name ="D", PathType ="query" });
params.Add(new Parameter{ Name ="D", PathType ="body" });

I need to find parameters that have the same Name (like: C and D ) where PathType equals path and query . Sorry for my English, it is a little bit difficult to explain. I want to find

 Name ="C", PathType ="path"
 Name ="C", PathType ="query"
 Name ="D", PathType ="path"
 Name ="D", PathType ="query"

Then remove all where PathType = "query" . Finally result should be

Name ="A", PathType ="path" 
Name ="B", PathType ="query"
Name ="C", PathType ="path" 
Name ="D", PathType ="path" 
Name ="D", PathType ="body" 

My code

var groupedParams = params.GroupBy(a => a.Name, StringComparer.InvariantCultureIgnoreCase).ToDictionary(t => t.Key);
foreach (var parameter in params) {
    if (groupedParams.ContainsKey(parameter.Name)) {
        var temp = groupedParams[parameter.Name];
        if (temp.Count(x => x.PathType.ToLower() == "path") == 1 && temp.Count(x => x.PathType.ToLower() == "query") == 1) {
            params.Remove(parameter);
        }
    }
}

I need to group by name but remove only when there are path and query for that name. Please suggest how can I do in in other way? Thanks

I need to group by name but remove only when there are path and query for that name. Please suggest how can I do in in other way?

If I were to assume that phrase is equal to this:

How do I remove a parameter with PathType="query" from a collection, if and only if there's another parameter with the same Name AND PathType="path" ?

Then you could do it with this statement:

params.RemoveAll(o => o.PathType == "query" && params.Any(p => p.Name == o.Name && p.PathType == "path"));

Update :

For case insensitive comparison (on PathType ):

params.RemoveAll(o => o.PathType.Equals("query", StringComparison.OrdinalIgnoreCase) && params.Any(p => p.Name == o.Name && p.PathType.Equals("path", StringComparison.OrdinalIgnoreCase)));

You could do that with this LINQ statement:

var cleanedParams = params.Where(p => p.PathType != "query" ||
    !params.Any(p2 => p2.Name == p.Name && p2.PathType != "query")).ToList();

I have some difficulty to understand your problem as it is not well stated. So here is what i have understood. It has 2 questions: Q1. Return those entries which has repeated names (eg c and d) where pathType has value query or path like you mentioned in your expected result.

Name ="C", PathType ="path"
Name ="C", PathType ="query"
Name ="D", PathType ="path"
Name ="D", PathType ="query"

if yes you can get it like:

var filteredList = param.Where(x => x.PathType == "query" || x.PathType == "path").ToList();
//Below list will have result.
var duplicateNameList = filteredList.GroupBy(x => x.Name).Where(x => x.Count() > 1).ToList();

Q2. Get the entries from the list where pathType =="query" or pathType=="path".

if yes here is the code:

 var result = param.Where(x => x.PathType != "query" && x.PathType!="path").ToList();

Let me know if i have misunderstood your question.

Well, first of all, you can't use params as variable's name because it's C# instruction.

Next. As I understand you want to have cycles. Ok, as I noted above, you can't modify collection ( papram in your case) inside foreach loop body. You can use something like this:

var groupedParams = _params.GroupBy(a => a.Name, StringComparer.InvariantCultureIgnoreCase).ToDictionary(t => t.Key);
int i = 0;
while (i != _params.Count)
{
    if (groupedParams.ContainsKey(parameter.Name))
    {
        var temp = groupedParams[parameter.Name];
        if (temp.Count(x => x.PathType.ToLower() == "path") == 1 && temp.Count(x => x.PathType.ToLower() == "query") == 1)
        {
            params.RemoveAt(i);
            continue;
        }
    }
    i++;
}

I've just rename params to _params to make it more correct. If params is just Parametr[] replace _params.Count with _params.Length .

It seems I found the solution. My code :

var paramList = params.Where(x => x.PathType.Equals("path") || x.PathType.Equals("query"));
var groupedParams  = paramList.GroupBy(a => a.Name, StringComparer.InvariantCultureIgnoreCase).ToDictionary(t => t.Key);
foreach (var item in groupedParams) {
    var temp = item.Value.Count() > 1;
    if (temp) {
        var paramToDelete = operation.parameters.FirstOrDefault(x => x.Name.ToLower() == item.Key.ToLower() && x.PathType == "query");
        if (paramToDelete != null) {
            operation.parameters.Remove(paramToDelete);
        }
    }
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM