请教一个无连接条件的签到、签退问题。谢谢

BiChangQing gh 经理  2014-01-22 04:12:21
签到、签退应一对出现,但有时存在多次重复签到的现象,
请问如保将表1生成表2.

数据原表(表1)如下:
人员编号 状态 日期 时间
5837 签到 2014-1-6 08.53.51
5837 签退 2014-1-6 08.53.59
5837 签到 2014-1-6 09.03.25
5837 签到 2014-1-6 10.04.05
5837 签退 2014-1-6 10.04.59
5837 签到 2014-1-6 10.26.39
5837 签到 2014-1-6 11.16.47
5837 签到 2014-1-6 11.57.18
5837 签退 2014-1-6 11.59.32
5837 签到 2014-1-6 13.36.35
5837 签到 2014-1-6 13.53.49
5837 签到 2014-1-6 14.51.36
5837 签到 2014-1-6 15.11.42
5837 签退 2014-1-6 15.38.56
5837 签到 2014-1-6 15.45.59
5837 签到 2014-1-6 16.39.02
5837 签退 2014-1-6 16.41.40
5837 签到 2014-1-6 16.47.40
5837 签退 2014-1-6 17.22.06
如何生成(表2)
人员编号 签到时间 签退时间
5837 08.53.51 08.53.59
5837 09.03.25
5837 10.04.05 10.04.59
5837 10.26.39
5837 11.16.47
5837 11.57.18 11.59.32
5837 13.36.35
5837 13.53.49
5837 14.51.36
5837 15.11.42 15.38.56
5837 15.45.59
5837 16.39.02 16.41.40
5837 16.47.40 17.22.06


...全文
190 点赞 收藏 10
写回复
10 条回复
以专业开发人员为伍 2014年01月22日
当然还有一个必须掌握的基本技能啦,就是要对“表1”和“表2”分别建立一个实体模型。不能拿着稀里糊涂地字符串叫做表。实际上比较规矩地先进行实体建模,说明了一个程序员的基本素质。
回复 点赞
以专业开发人员为伍 2014年01月22日
首先,要注意排序( orderby obj.人员, obj.时间) 其次就比较简单了,要注意“整理”过程中第一个if判断,它用来当机立断仅返回只有“签到”或者只有“签退”的数据。 最后就是要注意,整理过程是一个迭代器程序模式。
回复 点赞
以专业开发人员为伍 2014年01月22日
给你写个。假设数据全都是一天内的,可以这样测试:
using System;
using System.Collections.Generic;
using System.Linq;

namespace ConsoleApplication1
{
    public class 记录
    {
        public string 人员;
        public string 类型;
        public TimeSpan 时间;
    }

    public class 结果
    {
        public string 人员;
        public string 签到;
        public string 签退;
    }

    class Program
    {
        static void Main(string[] args)
        {
            string 表1 = @"5837 签到 2014-1-6 08.53.51
 5837 签退 2014-1-6 08.53.59
 5837 签到 2014-1-6 09.03.25
 5837 签到 2014-1-6 10.04.05
 5837 签退 2014-1-6 10.04.59
 5837 签到 2014-1-6 10.26.39
 5837 签到 2014-1-6 11.16.47
 5837 签到 2014-1-6 11.57.18
 5837 签退 2014-1-6 11.59.32
 5837 签到 2014-1-6 13.36.35
 5837 签到 2014-1-6 13.53.49
 5837 签到 2014-1-6 14.51.36
 5837 签到 2014-1-6 15.11.42
 5837 签退 2014-1-6 15.38.56
 5837 签到 2014-1-6 15.45.59
 5837 签到 2014-1-6 16.39.02
 5837 签退 2014-1-6 16.41.40
 5837 签到 2014-1-6 16.47.40
 5837 签退 2014-1-6 17.22.06
 5838 签到 2014-1-6 9.0.0
 5838 签退 2014-1-6 17.33.38";
            var table1 = (from line in 表1.Split(new char[] { '\r', '\n' }, StringSplitOptions.RemoveEmptyEntries)
                          let sp = line.Split(new char[] { ' ' }, StringSplitOptions.RemoveEmptyEntries)
                          let sm = sp[3].Split('.')
                          let time = new TimeSpan(int.Parse(sm[0]), int.Parse(sm[1]), int.Parse(sm[2]))
                          let obj = new 记录
                          {
                              人员 = sp[0],
                              类型 = sp[1],
                              时间 = time
                          }
                          orderby obj.人员, obj.时间
                          select obj).ToList();
            var table2 = 整理(table1, 0).ToList();
            Console.WriteLine("_____________________________________总共{0}行数据!", table2.Count);
            foreach (var line in table2)
                Console.WriteLine("{0}\t{1}-{2}", line.人员, line.签到, line.签退);
            Console.WriteLine("_____________________________________按任意键结束");
            Console.ReadKey();
        }

        private static IEnumerable<结果> 整理(List<记录> table1, int index)
        {
        begin:
            if (index + 1 >= table1.Count)
                yield break; ;

            var obj = table1[index];
            if (index + 1 == table1.Count || obj.类型 == "签退" || table1[index + 1].人员 != obj.人员 || table1[index + 1].类型 == obj.类型)
            {
                yield return new 结果
                 {
                     人员 = obj.人员,
                     签退 = obj.类型 == "签退" ? obj.时间.ToString() : null,
                     签到 = obj.类型 == "签到" ? obj.时间.ToString() : null
                 };
                index++;
            }
            else
            {
                yield return new 结果
                {
                    人员 = obj.人员,
                    签到 = obj.时间.ToString(),
                    签退 = table1[index + 1].时间.ToString()
                };
                index += 2;
            }
            goto begin;
        }
    }

}
打印结果为: _____________________________________总共14行数据! 5837 08:53:51-08:53:59 5837 09:03:25- 5837 10:04:05-10:04:59 5837 10:26:39- 5837 11:16:47- 5837 11:57:18-11:59:32 5837 13:36:35- 5837 13:53:49- 5837 14:51:36- 5837 15:11:42-15:38:56 5837 15:45:59- 5837 16:39:02-16:41:40 5837 16:47:40-17:22:06 5838 09:00:00-17:33:38 _____________________________________按任意键结束
回复 点赞
是时候重装系统了 2014年01月22日
这不就是传说中的考勤嘛,这个算法可有点复杂哦。比如你的签到 、 应该跟签退是匹配的 所谓的一进一出嘛,楼上几位可能说法欠妥。 我个人觉得是 一个人签到了 必须匹配到一条签退。 这样就是一个完整的记录。
回复 点赞
Regan-lin 2014年01月22日
引用 1 楼 liuqian4243 的回复:
一天内,第一次是签到,最后一次是 签退 先按天分组,只取最大的最小值。 然后,再生成你第一个表格就是了。
+1
回复 点赞
bdmh 2014年01月22日
先dinctint人员编号,然后根据编号取min(时间)和max(时间)
回复 点赞
枫飞叶 2014年01月22日
按时间来算超时了就记录,应该是签到-->签退 是已分钟来来算的
回复 点赞
Ny-6000 2014年01月22日
当然,如果一天内,会有多次签到和多次签退,这个办法就不行了。
回复 点赞
Ny-6000 2014年01月22日
一天内,第一次是签到,最后一次是 签退 先按天分组,只取最大的最小值。 然后,再生成你第一个表格就是了。
回复 点赞
发动态
发帖子
C#
创建于2007-09-28

8.5w+

社区成员

64.0w+

社区内容

.NET技术 C#
社区公告
暂无公告