从列表C#中获取唯一的3位数拉链

时间:2013-12-05 17:19:46

标签: c# .net regex

我有一个代表美国邮政编码的整数列表,我希望根据邮政编码的前三位数得到唯一值。例如,这是我的清单:

10433
30549
10456
54933
60594
30569
30659

我的结果应仅包含:

10433
30549
54933
60594
30659

从我的列表中排除的美国邮政编码是: 10456 30659 ,因为我已经拥有包含104xx和306xx的ZIP。

我真的不知道怎么做到这一点,我想这并不难,但我不知道。我已经创建了一个函数,它为我保存了前三位数字,并且我在每个zip的末尾添加了一些随机的2位数字。但它没有成功,因为我得到了例如10423但10423不在我的列表中,并且我没有特定的模式,我的所有数字都有一个范围内的最后2位数。

2 个答案:

答案 0 :(得分:12)

一点Linq应该工作。如果使用int s列表:

var zips = new[] { 10433, 30549, 10456, 54933, 60594, 30569, 30659 };
var results = zips.GroupBy(z => z / 100).Select(g => g.First());

或者如果使用string s列表:

var zips = new[] { "10433", "30549", "10456", "54933", "60594", "30569", "30659" };
var results = zips.GroupBy(z => z.Remove(3)).Select(g => g.First());

另一种解决方案是使用自定义IEqualityComparer<T>。对于int s:

class ZipComparer : IEqualityComparer<int> {
    public bool Equals(int x, int y) {
        return x / 100 == y / 100;
    }
    public int GetHashCode(int x) {
        return x / 100;
    }
}

对于string s:

class ZipComparer : IEqualityComparer<string> {
    public bool Equals(string x, string y) {
        return x.Remove(3) == y.Remove(3);
    }
    public int GetHashCode(string x) {
        return x.Remove(3).GetHashCode();
    }
}

然后使用它,您只需拨打Distinct

即可
var result = zips.Distinct(new ZipComparer());

最后,您还使用了MoreLINQDistinctBy扩展方法(也可在NuGet上找到):

var results = zips.DistinctBy(z => z / 100);
// or
var results = zips.DistinctBy(z => z.Remove(3));

答案 1 :(得分:2)

这里流行的答案给出了代码,但没有解决问题。问题是你似乎没有算法。所以......

您如何在纸上解决此问题?

我认为这个过程会是这样的:

  1. 对于每个号码,确定3位数字前缀
  2. 如果您还没有带该前缀的zip,请保留号码
  3. 如果您已经有一个带有该前缀的zip,请丢弃该号码
  4. 你会如何在代码中写这个?

    嗯,你需要一些东西:

    • 用于跟踪您找到的前缀以及您保留的值的存储桶。
    • 所有项目的循环
    • 确定前缀的方法

    这是编写此内容的一种方法(您可以将其转换为使用字符串作为练习):

    ICollection<int> GetUniqueZipcodes(int[] zips)
    {
        Dictionary<int, int> bucket = new Dictionary<int,int>();
        foreach (var zip in zips)
        {
            int prefix = GetPrefix(zip);
            if(!bucket.ContainsKey(prefix))
            {
                bucket.Add(prefix, zip);
            }
        }
        return bucket.Values;
    }
    
    int GetPrefix(int zip)
    {
        return zip / 100;
    }
    

    简明扼要

    现在,如今许多程序员都会说“OMG这么多行代码可能只是一行代码”。他们是对的,它可以。借用p.s.w.g的答案,这可以(以一种非常易读的方式)浓缩为:

    var results = zips.GroupBy(z => z / 100).Select(g => g.First());
    

    那么这是如何工作的? zips.GroupBy(z => z/100)执行分段操作。最终会得到一组如下所示的组:

    { 
        104: { 10433, 10456 },
        305: { 30549, 30569 },
        549: { 54933 },
        605: { 60594 },
        306: { 30659 }
    }
    

    然后我们使用.Select(g => g.First()),它从每个组中获取第一项。