一个泛型应用示例:将一组已经排序的条形码按照"相邻编号连续"分组

bambuz 2012-12-20 05:02:56
因实际应用中的需要, 创建了一个泛型类的实例, 欢迎拍砖.


using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;


// 一个泛型应用示例
// 应用场景: 将一组已经排序的条形码按照"相邻编号连续"分组

public class MyGen<T> where T : IMyBar
{
private List<T> list = null;

public MyGen()
{
list = new List<T>();
}

public void Add(T t)
{
list.Add(t);
}

public void AddRange(List<T> otherList)
{
list.AddRange(otherList);
}

// 计算出分组列表
public List<Range<T>> GetRangeList()
{
List<Range<T>> resultList = new List<Range<T>>();

list.Sort((a, b) => String.Compare(a.Barcode, b.Barcode)); //按照条形码编号排序

for (int i = 0; i < list.Count; i++)
{
if (resultList.Count > 0)
{
Range<T> curRange = resultList.Last();
string nextBarcode = curRange.Start.GetEnd(curRange.Count + 1);
if (list[i].Barcode.Equals(nextBarcode))
{
curRange.Add(list[i]);
}
else
{
resultList.Add(new Range<T>(list[i]));
}
}
else
{
resultList.Add(new Range<T>(list[i]));
}
}

return resultList;
}
}

public class Bar : IMyBar
{
private static readonly int fixedLen = 12;//条码固定长度为12, 编码为 MMCCVVxxxxxx, 后6位为数字,从1开始计数至999999,不足位以0填充

// 判断是否为符合要求的条形码编号
public static bool IsMatch(string barcode)
{
bool result = false;
int index = 0;
if (barcode.Length == fixedLen
&& Int32.TryParse(barcode.Substring(6), out index)
&& index > 0)
{
result = true;
}
return result;
}

// ctor
public Bar()
{
Barcode = String.Empty;
}

public Bar(string barcode)
{
if (IsMatch(barcode))
{
Barcode = barcode;
}
else
{
Barcode = String.Empty;
}
}

// 前缀
public string Prefix
{
get
{
if (IsMatch(Barcode))
{
return Barcode.Substring(0, 6);
}
else
{
return String.Empty;
}
}
}

// 条形码
public string Barcode { get; private set; }

// 获得指定间隔的后续条形码
public string GetEnd(int count)
{
if (count > 0 && IsMatch(Barcode))
{
int index = Convert.ToInt32(Barcode.Substring(6));
if (!(count + index > 1000000))
{
return String.Format("{0}{1:d06}", Prefix, index + count - 1);
}
}
return String.Empty;
}

// 输出
public override string ToString()
{
return Barcode;
}
}

// 泛型类型必须实现的接口: 一个条形码字符串属性 及计算指定间隔的后续条形码的方法
public interface IMyBar
{
string Barcode { get; }
string GetEnd(int count);
}

// 分组信息
public class Range<T> where T : IMyBar
{
public T Start { get; private set; }
public T End { get; private set; }
public int Count { get; private set; }

public Range(T start)
{
Start = start;
End = start;
Count = 1;
}

public int Add(T t)
{
End = t;
return ++Count;
}
}

// 示例
public class Program
{
public static void Main(string[] args)
{
string[] bcs = new string[]
{
"AABBCC000001", "AABBCC000002", "AABBCC000003", "AABBCC000006", "AABBCC000007",
"AABBCC000009", "AABBCD000001", "AABBCD000002", "ADBBCC000001", "DDDDDD"
};
MyGen<Bar> myGen = new MyGen<Bar>();
for (int i = 0; i < bcs.Length; i++)
{
if (Bar.IsMatch(bcs[i]))
{
myGen.Add(new Bar(bcs[i]));
}
}

List<Range<Bar>> list = myGen.GetRangeList();
Console.WriteLine("开始条形码 结束条形码 数量");
foreach (var item in list)
{
Console.WriteLine("{0} {1} {2}", item.Start, item.End, item.Count);
}
}
}

class Product : Bar
{
public Product(string barcode)
: this("unknown", barcode)
{
}

public Product(string name, string barcode)
: base(barcode)
{
Name = name;
CreateTime = DateTime.Now;
}

public string Name { get; set; }
public DateTime CreateTime { get; set; }


public override string ToString()
{
return String.Format("{0},{1},{2}", Name, Barcode, CreateTime);
}

public static List<Range<Product>> GetRangeList(List<Product> list)
{
MyGen<Product> productGen = new MyGen<Product>();
productGen.AddRange(list);

return productGen.GetRangeList();
}

//MyGen<Product> myGen = new MyGen<Product>();
//for (int i = 0; i < bcs.Length; i++)
//{
// if (Bar.IsMatch(bcs[i]))
// {
// myGen.Add(new Product(bcs[i]));
// }
//}

//List<Range<Product>> list = myGen.GetRangeList();
//Console.WriteLine("开始条形码 结束条形码 数量");
//foreach (var item in list)
//{
// Console.WriteLine("{0} {1} {2}", item.Start, item.End, item.Count);
//}
}
...全文
251 10 打赏 收藏 转发到动态 举报
AI 作业
写回复
用AI写文章
10 条回复
切换为时间正序
请发表友善的回复…
发表回复
小亮Lee 2012-12-21
  • 打赏
  • 举报
回复
来学习学习!!!
threenewbee 2012-12-21
  • 打赏
  • 举报
回复
.NET 3.5没有 Zip,需要4.0以上。 你可以自己实现一个
IEnumerable<TResult> Zip<TSource1, TSource2, TResult>(this IEnumerable<TSource1> source1, IEnumerable<TSource2> source2, Func<TSource1, TSource2, TResult> selector)
{
    var list1 = source1.ToList();
    var list2 = source2.ToList();
    for (int i = 0; i < (list1.Count > list2.Count ? list2.Count : list1.Count); i++)
        yield return selector(list1[i], list2[i]);
}
bambuz 2012-12-21
  • 打赏
  • 举报
回复
引用 6 楼 caozhy 的回复:
C# code ? 123456789101112131415161718192021222324252627282930313233 using System; using System.Linq; using System.Text.RegularExpressions; namespace ConsoleApplication1 { public class……
嗯, Linq + 正则表达式, , 很强大!! 虽然一时还看不明白. 还有, 这里的 ZIP 没有定义哟!
段传涛 2012-12-21
  • 打赏
  • 举报
回复
收藏 正好都比对学习一下。
threenewbee 2012-12-20
  • 打赏
  • 举报
回复
using System;
using System.Linq;
using System.Text.RegularExpressions;

namespace ConsoleApplication1
{
    public class Program
    {
        public static void Main(string[] args)
        {
            string[] bcs = new string[] 
            {
                "AABBCC000001", "AABBCC000002", "AABBCC000003", "AABBCC000006", "AABBCC000007", 
                "AABBCC000009", "AABBCD000001", "AABBCD000002", "ADBBCC000001", "DDDDDD" 
            };
            int gid = 0;
            Func<string, string, bool> pred = (x, y) =>
                {
                    if (!Regex.IsMatch(x, "\\d+$") || !Regex.IsMatch(y, "\\d+$")) return false;
                    if (Regex.Match(x, "^[A-Za-z]+").Value != Regex.Match(y, "^[A-Za-z]+").Value) return false;
                    return (int.Parse(Regex.Match(x, "\\d+$").Value) - int.Parse(Regex.Match(y, "\\d+$").Value)) == 1;
                };
            var query = bcs.Take(1).Select(x => new { x, id = gid })
                .Concat(bcs.Skip(1).Zip(bcs, (i2, i1) => new { x = i2, id = pred(i2, i1) ? gid : ++gid }))
                .GroupBy(x => x.id);
            Console.WriteLine("开始条形码     结束条形码   数量");
            foreach (var item in query)
            {
                Console.WriteLine("{0}   {1}  {2}", item.Min(x => x.x), item.Max(x => x.x), item.Count());
            }
        }
    }
}
就这么几行就行了。
段传涛 2012-12-20
  • 打赏
  • 举报
回复
定义个类实现 听简单方便的。 不过还是支持一下,能给大家分享也是挺好的。
threenewbee 2012-12-20
  • 打赏
  • 举报
回复
不但没看出用泛型有什么用,就是你定义接口和一个基类也没有任何必要。 MyGen也没有必要。Main写的也罗嗦。
bambuz 2012-12-20
  • 打赏
  • 举报
回复
主要是这个方法中有几个类中需要调用:
// 计算出分组列表     public List<Range<T>> GetRangeList()
同时写成泛型也练练手.
你的选择H 2012-12-20
  • 打赏
  • 举报
回复
stonespace 2012-12-20
  • 打赏
  • 举报
回复
这不需要用泛型吧?用类就可以解决,

111,094

社区成员

发帖
与我相关
我的任务
社区描述
.NET技术 C#
社区管理员
  • C#
  • AIGC Browser
  • by_封爱
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告

让您成为最强悍的C#开发者

试试用AI创作助手写篇文章吧