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

BiChangQing 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


...全文
276 10 打赏 收藏 转发到动态 举报
AI 作业
写回复
用AI写文章
10 条回复
切换为时间正序
请发表友善的回复…
发表回复
  • 打赏
  • 举报
回复
当然还有一个必须掌握的基本技能啦,就是要对“表1”和“表2”分别建立一个实体模型。不能拿着稀里糊涂地字符串叫做表。实际上比较规矩地先进行实体建模,说明了一个程序员的基本素质。
  • 打赏
  • 举报
回复
首先,要注意排序( orderby obj.人员, obj.时间) 其次就比较简单了,要注意“整理”过程中第一个if判断,它用来当机立断仅返回只有“签到”或者只有“签退”的数据。 最后就是要注意,整理过程是一个迭代器程序模式。
  • 打赏
  • 举报
回复
给你写个。假设数据全都是一天内的,可以这样测试:
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 _____________________________________按任意键结束
  • 打赏
  • 举报
回复
这不就是传说中的考勤嘛,这个算法可有点复杂哦。比如你的签到 、 应该跟签退是匹配的 所谓的一进一出嘛,楼上几位可能说法欠妥。 我个人觉得是 一个人签到了 必须匹配到一条签退。 这样就是一个完整的记录。
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
  • 打赏
  • 举报
回复
一天内,第一次是签到,最后一次是 签退 先按天分组,只取最大的最小值。 然后,再生成你第一个表格就是了。

111,094

社区成员

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

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

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