Java 查找一周内登录两次的用户

Java 查找一周内登录两次的用户,java,algorithm,data-structures,Java,Algorithm,Data Structures,XYZ公司每天都在一些日志文件中存储用户的日志信息。打印一周内登录两次的用户 例如: weekday1.log weekday2.log weekday3.log weekday4.log weekday5.log weekday6.log weekday7.log 每个log文件都包含在特定日期登录到XYZ站点的用户的姓名。现在从上面的文件中搜索登录两次的用户的姓名 这个问题是在一次采访中问我的我有一个很明显的答案,就是按顺序扫描文件,因为我不太擅长DS和Algo。有人能提供一些

XYZ公司每天都在一些日志文件中存储用户的日志信息。打印一周内登录两次的用户

例如:

weekday1.log

weekday2.log

weekday3.log

weekday4.log

weekday5.log

weekday6.log

weekday7.log
每个
log
文件都包含在特定日期登录到XYZ站点的用户的姓名。现在从上面的文件中搜索登录两次的用户的姓名


这个问题是在一次采访中问我的我有一个很明显的答案,就是按顺序扫描文件,因为我不太擅长DS和Algo。有人能提供一些有效的方法来查找吗。谢谢。

日志不是存储数据的标准结构

考虑一下,如果用户名出现异常,则可能会打印用户名两次或三次。在这种情况下,我们无法得到准确的结果。如果某个开发人员打印了一个带有用户名的日志以供澄清,这将破坏整个过程

建议以标准格式(如SQL等)存储这些内容,以便更容易、更快和准确地从中获取数据


如果你盲目地认为你需要单独使用用户名,那么它将是一个普通的文件搜索。

我认为不可能做得比线性好,但是,有可能比二次做得更好,这是天真的解决方案。您可以逐行扫描文件,在其中为不可见的名称创建一个新的映射条目,或者增加名称在映射中的出现次数。这假设名称是唯一的。最后,在映射上迭代值为2的条目。这也假设你的意思是在整个星期内访问了两次

public class Main
{
  public static void main(String[] args) throws Exception 
  {
    String[] files = { /* Your files */ };
    List<String> lines;
    Map<String, Integer> map = new TreeMap<>();
    Integer occurrences;
    for (String f : files) {
        lines = Files.readAllLines(Paths.get(f), Charset.defaultCharset());
        for (String entry : lines) {
          occurrences = map.get(entry);
          if (occurrences == null)
            map.put(entry, 1);
          else
            map.put(entry, occurrences + 1);
        }
    }
    for (Map.Entry<String, Integer> entry : map.entrySet())
        if (entry.getValue() == 2)
            System.out.println(entry.getKey() + " occurred twice.");
  }
}
公共类主
{
公共静态void main(字符串[]args)引发异常
{
String[]files={/*您的文件*/};
列出行;
Map Map=newtreemap();
整数出现次数;
用于(字符串f:文件){
lines=Files.readAllLines(path.get(f),Charset.defaultCharset());
for(字符串输入:行){
事件=map.get(条目);
如果(出现次数==null)
地图放置(条目,1);
其他的
地图放置(条目,事件+1);
}
}
对于(Map.Entry:Map.entrySet())
if(entry.getValue()==2)
System.out.println(entry.getKey()+“出现两次”);
}
}

可以这样做:

BufferedReader fr;
String usrid="";
int frequency=0;

for(int i=1;i<8;i++){
    try{
        fr = new BufferedReader(new FileReader("filepath/weekday"+i+".log"));

        String dataRow = fr.readLine();     
        while (dataRow != null){
            usrid = ..... ;//retrieve the userId from the dataRow
            for(int j=0;j<user.length; j++){
                frequency=Integer.parseInt(user[j][1]);
                if(usrid.equalsIgnoreCase(user[j][0])){
                    user[j][1]=String.valueOf(frequency+1);
                }
            }
            dataRow = fr.readLine(); 
        } 
    }
    catch(Exception e){}
}
首先,将所有用户ID和初始登录频率存储在2D数组中,例如:

    String [][] user = {{"john","0"}, {"bill","0"}, {"steve","0"},....}; 
    //Of course you didn't do this hardcoded. You may do this using loop
然后像这样做:

BufferedReader fr;
String usrid="";
int frequency=0;

for(int i=1;i<8;i++){
    try{
        fr = new BufferedReader(new FileReader("filepath/weekday"+i+".log"));

        String dataRow = fr.readLine();     
        while (dataRow != null){
            usrid = ..... ;//retrieve the userId from the dataRow
            for(int j=0;j<user.length; j++){
                frequency=Integer.parseInt(user[j][1]);
                if(usrid.equalsIgnoreCase(user[j][0])){
                    user[j][1]=String.valueOf(frequency+1);
                }
            }
            dataRow = fr.readLine(); 
        } 
    }
    catch(Exception e){}
}
BufferedReader-fr;
字符串usrid=“”;
整数频率=0;
对于(inti=1;i,我们都知道“日志不是存储数据的标准结构”。
您必须使用纯逻辑来查找登录详细信息。
通过使用错误消息,您必须区分异常和有效登录详细信息。

如果凭证有效,则增加计数。通过这种方式,只能知道..

假设每个登录的文件只有一行,并且名称是唯一的,那么我将通过拥有一组访问次数超过两次的名称和一个访问次数的名称映射来实现此目的。然后执行此操作

  • 读名字
  • 如果名称在集合中,则读取下一个名称(返回到1)
  • 检查是否在地图中-如果未添加,则检查访问次数-如果1递增,如果2从地图中删除并添加到集合
  • 循环1-3,同时读取更多名称
  • 打印地图上访问过两次的姓名

  • 假设

    • 文件数据如下所示(即单行上的唯一名称)

      davidtennant
      莎拉·简·史密斯
      戴勒克证券公司
      埃米利娅池塘
      
    • 存储在同一目录中的所有文件


    BufferedReader br;
    文件目录=新文件(“日志目录”);
    File[]logFiles=dir.listFiles();
    整数极限=2;
    Set moreThanLimit=新HashSet();
    映射名称=新的HashMap();
    用于(文件f:日志文件)
    {
    //我需要在这里试一试
    br=新的BufferedReader(新的文件读取器(f));
    字符串名;
    而((name=br.readLine())!=null)
    {
    如果(超过限制。包含(名称))
    继续;
    整数频率=name.get(name);
    如果(频率==极限)
    {
    超过限制。添加(名称);
    名称。删除(名称)
    继续;
    }
    else if(freq==null)
    频率=0;
    name.put(name,++freq);
    }
    }
    对于(条目e:names.entrySet())
    如果(如getValue()==限制)
    System.out.println(e.getKey()
    
    我的建议如下:

    • 扫描日志,创建用户对象(具有属性username、timesLoggedIn) 并将它们添加到二叉搜索树中
    • 对于您断言的每个元素,请确保在找到应该断言的位置(由CompareTo的用户)时,更新TimeLoggedIn(如果它已与+1一起存在)
    • 最后,扫描二进制搜索树并打印TimeLoggedIn等于2的所有元素
    为什么更快?因为当应用find\u position/or元素时,您只需排除树中您知道不需要的部分,因此您根本不需要检查。在我们的例子中,这是使用compareTo进行评估的)因此如果我们想找到用户名为“johnDoe”的用户在一个拥有100万用户的二元搜索树中,第一次评估“johndoe”与根用户的用户名相比,我们将排除树的一半,即500.000个元素,因此想象一下,我们获得所需结果的速度有多快


    注意:为了使二元搜索树以最佳方式工作,它应该是平衡的,有一些算法和工具可以真正平衡二元搜索树。

    我认为,这与算法无关。因为你实际上必须一次浏览所有数据,所以按顺序浏览它是完美的,只要你只需我想他们只是想看看你对Java的了解是否足以实现它,但他们真的不在
    BufferedReader br;
    File dir = new File("TheLogDir");
    File[] logFiles = dir.listFiles();
    int limit = 2;
    Set<String> moreThanLimit = new HashSet<String>();
    Map<String, Integer> names = new HashMap<String, Integer>();
    
    for(File f : logFiles)
    {
        // Will need a try/catch here
        br = new BufferedReader(new FileReader(f));
        String name;     
        while ((name = br.readLine()) != null)
        {
             if(moreThanLimit.contains(name))
                  continue;
             Integer freq = names.get(name);
             if(freq == limit)
             {
                 moreThanLimit.add(name);
                 names.remove(name)
                 continue;
             }
             else if(freq == null)
                 freq = 0;
             names.put(name, ++freq);
        }
    }
    
    for(Entry<String,Integer> e : names.entrySet())
        if(e.getValue() == limit)
             System.out.println(e.getKey()