Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/linq/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 如何筛选列表,使任何成员都不是另一个成员的子字符串_C#_Linq_Distinct - Fatal编程技术网

C# 如何筛选列表,使任何成员都不是另一个成员的子字符串

C# 如何筛选列表,使任何成员都不是另一个成员的子字符串,c#,linq,distinct,C#,Linq,Distinct,我有一个包含字符串项的列表,但是一些字符串包含类似的文本,我正在尝试获取不同的列表 我的清单包括: -Customers\\Order1 -Customers\\Order1\\Product1 -Customers\\Order2\\Product1 -Customers\\Order2\\Product1\\Price 从这个列表中,我需要得到: -Customers\\Order1\\Product1 -Customers\\Order2\\Product1\\Price 基本上,如果

我有一个包含字符串项的列表,但是一些字符串包含类似的文本,我正在尝试获取不同的列表

我的清单包括:

-Customers\\Order1
-Customers\\Order1\\Product1
-Customers\\Order2\\Product1
-Customers\\Order2\\Product1\\Price
从这个列表中,我需要得到:

-Customers\\Order1\\Product1
-Customers\\Order2\\Product1\\Price

基本上,如果某个字符串在列表中的另一个字符串中,我想省略它?

上一个例程的问题是,当有匹配项时,应该中止第二个列表中的搜索。否则,它在其他项目上仍然有效

编辑:新例程:

class Program
{
    private static IEnumerable<string> SelectUnique(IEnumerable<string> list)
    {
        // iterate the list..
        foreach (var item1 in list)
            // you don't want to match the same item.
            if (!list.Where(item2 => item1 != item2)
                // search for items where it start with the current item. (notice the ! before the list.Where)
                .Any(item2 => item2.StartsWith(item1)))
                    yield return item1;
    }


    static void Main(string[] args)
    {

        List<string> list = new List<string>();
        list.Add("Customers\\Order1\\Product1");
        list.Add("Customers\\Order2\\Product1");
        list.Add("Customers\\Order2\\Product1\\Price");
        list.Add("Customers\\Order1");
        list.Add("Customers\\Order3\\Price");



        var results = SelectUnique(list);

        foreach (var item in results)
            Console.WriteLine(item);

        Console.ReadKey();

    }
}
类程序
{
私有静态IEnumerable SelectUnique(IEnumerable列表)
{
//迭代列表。。
foreach(列表中的变量项1)
//您不想匹配同一项。
if(!list.Where(item2=>item1!=item2)
//搜索以当前项目开头的项目。(请注意列表前的!where)
.Any(item2=>item2.StartsWith(item1)))
收益回报项目1;
}
静态void Main(字符串[]参数)
{
列表=新列表();
添加(“客户\\订单1\\产品1”);
添加(“客户\\订单2\\产品1”);
添加(“客户\\订单2\\产品1\\价格”);
列表。添加(“客户\\订单1”);
添加(“客户\\订单3\\价格”);
var结果=选择唯一(列表);
foreach(结果中的var项目)
控制台写入线(项目);
Console.ReadKey();
}
}

您可以使用一点LINQ和一个
foreach
循环来实现这一点,如:

List<string> outputList = new List<string>();
foreach (var str in originalList)
{
    if (!outputList.Contains(str)
        && !originalList.Any(r => r!= str && r.Contains(str)))
    {
        outputList.Add(str);
    }
}
您将获得
输出列表
,如下所示:

Customers\\Order1\\Product1
Customers\\Order2\\Product1\\Price

如果这些值是真正的路径,并且您想要处理子目录,那么您需要确保您也在处理一个名称是另一个名称的子字符串,但它们是不同的路径的情况。即
Customer\\Order1
Customer\\Order10

public static class Extensions
{
    public static IEnumerable<string> DistinctBySubString(this IEnumerable<string> strings)
    {
        var results = new List<string>();
        foreach (var s in strings)
        {
            bool add = true;
            for(int i=results.Count-1; i>=0; i--)
            {
                if (IsSubDirectoryOf(results[i],s))
                {
                    results.RemoveAt(i);
                }
                else if (IsSubDirectoryOf(s,results[i]))
                {
                    add = false;
                }

            }
            if (add)
                results.Add(s);
        }
        return results;
    }

    private static bool IsSubDirectoryOf(string dir1, string dir2)
    {
        DirectoryInfo di1 = new DirectoryInfo(dir1);
        DirectoryInfo di2 = new DirectoryInfo(dir2);
        bool isParent = false;
        while (di2.Parent != null)
        {
            if (di2.Parent.FullName == di1.FullName)
            {
                isParent = true;
                break;
            }
            else di2 = di2.Parent;
        }
        return isParent;
    }
}
公共静态类扩展
{
公共静态IEnumerable DistinctBySubString(此IEnumerable字符串)
{
var results=新列表();
foreach(字符串中的变量s)
{
bool add=true;
对于(int i=results.Count-1;i>=0;i--)
{
if(发布董事(结果[i],s))
{
结果:RemoveAt(i);
}
否则如果(发布董事,结果[i]))
{
add=false;
}
}
如果(添加)
结果:添加(s);
}
返回结果;
}
私有静态bool IsSubDirectoryOf(字符串dir1,字符串dir2)
{
DirectoryInfo di1=新的DirectoryInfo(dir1);
DirectoryInfo di2=新的DirectoryInfo(dir2);
bool isParent=false;
while(di2.Parent!=null)
{
if(di2.Parent.FullName==di1.FullName)
{
isParent=true;
打破
}
else di2=di2.父项;
}
返回isParent;
}
}
像这样使用它:

List<string> strings = new List<string>()
{
    "Customers\\Order1",
    "Customers\\Order10",
    "Customers\\Order1\\Product1",
    "Customers\\Order2\\Product1",
    "Customers\\Order2\\Product1\\Price"
};



foreach (var result in strings.DistinctBySubString())
{
    Console.WriteLine(result);
}
List strings=新列表()
{
“客户\\订单1”,
“客户\\Order10”,
“客户\\订单1\\产品1”,
“客户\\订单2\\产品1”,
“客户\\订单2\\产品1\\Price”
};
foreach(var结果为strings.DistinctBySubString())
{
控制台写入线(结果);
}

目录匹配基于此答案中的代码:

如果项目的顺序无关紧要,则需要将列表从最长到最短排序,然后为
Distinct
LINQ方法提供自定义相等比较器

比较器同时实现
GetHashCode
Equals
。由于除非散列码相等,否则不会调用
Equals
,因此您可以通过始终返回
0
将其取出。
GetHashCode
的规则规定,不相等的事物可以返回相同的哈希代码,这样就不会破坏这里的语义

然后,
Equals
方法只是比较旧字符串是否以新字符串开头。新字符串作为第一个参数传入,旧字符串作为第二个参数传入

我们的比较器如下所示:

public class StartsWithEqualityComparer : IEqualityComparer<String>
{
   #region IEqualityComparer implementation

   public bool Equals (string x, string y)
   {
      return y.StartsWith (x);
   }

   public int GetHashCode (string obj)
   {
      return 0;
   }

   #endregion
}

最后,如果有必要,您可以使用
Sort
方法将列表重新排序为必要的顺序(按字母顺序排列)。

我认为这最好作为LINQ查询来完成

var input = new List<string>()
{
    "Customers\\Order1",
    "Customers\\Order1\\Product1",
    "Customers\\Order2\\Product1",
    "Customers\\Order2\\Product1\\Price",
};

var query =
    from x in input
    where !input.Any(y => y != x && y.Contains(x))
    select x;

var result = query.ToList();
var输入=新列表()
{
“客户\\订单1”,
“客户\\订单1\\产品1”,
“客户\\订单2\\产品1”,
“客户\\订单2\\产品1\\价格”,
};
变量查询=
从x输入
哪里input.Any(y=>y!=x&&y.Contains(x))
选择x;
var result=query.ToList();
我从中得到:


如果实际需要按子路径而不是按子字符串进行搜索,则此操作有效:

var input = new List<string>()
{
    "Customers\\Order1",
    "Customers\\Order1\\Product10",
    "Customers\\Order1\\Product1",
    "Customers\\Order2\\Product1",
    "Customers\\Order2\\Product1\\Price",
};

var paths = input.ToDictionary(x => x, x => x.Split('\\'));

var query =
    from x in input
    where !input
        .Any(y => y.Length > x.Length
            && paths[x]
                .Zip(paths[y], (p1, p2) => new { p1, p2 })
                .All(p => p.p1 == p.p2))
    select x;

var result = query.ToList();
var输入=新列表()
{
“客户\\订单1”,
“客户\\订单1\\产品10”,
“客户\\订单1\\产品1”,
“客户\\订单2\\产品1”,
“客户\\订单2\\产品1\\价格”,
};
var path=input.ToDictionary(x=>x,x=>x.Split('\\');
变量查询=
从x输入
哪里输入
.任意(y=>y.长度>x.长度
&&路径[x]
.Zip(路径[y],(p1,p2)=>new{p1,p2})
.All(p=>p.p1==p.p2))
选择x;
var result=query.ToList();
我得到这个结果:


你能给我看一些代码吗?定义字符串列表<代码>列表?使用
Distinct()
method@JeroenvanLangen
Distinct()
单独在这里是不够的。看看示例输出。列表中项目的顺序是否保证像您的示例输入那样从最不特定到最特定?或者,
-Customers\\Order2\\Product1\\Price
能排在
-Customers\\Order2\\Product1
前面吗?@DrewJordan如果你读了整个问题,它就很清楚了。如果你只读c的第一句话
var input = new List<string>()
{
    "Customers\\Order1",
    "Customers\\Order1\\Product1",
    "Customers\\Order2\\Product1",
    "Customers\\Order2\\Product1\\Price",
};

var query =
    from x in input
    where !input.Any(y => y != x && y.Contains(x))
    select x;

var result = query.ToList();
var input = new List<string>()
{
    "Customers\\Order1",
    "Customers\\Order1\\Product10",
    "Customers\\Order1\\Product1",
    "Customers\\Order2\\Product1",
    "Customers\\Order2\\Product1\\Price",
};

var paths = input.ToDictionary(x => x, x => x.Split('\\'));

var query =
    from x in input
    where !input
        .Any(y => y.Length > x.Length
            && paths[x]
                .Zip(paths[y], (p1, p2) => new { p1, p2 })
                .All(p => p.p1 == p.p2))
    select x;

var result = query.ToList();