公司XYZ每天在一些日志文件中存储用户的日志信息。打印一周内登录两次的用户。
示例:
weekday1.log
weekday2.log
weekday3.log
weekday4.log
weekday5.log
weekday6.log
weekday7.log
每个log
文件都包含特定日期登录到XYZ站点的用户名。现在从上面的文件中搜索登录两次的用户的名称。
在接受采访时我问过这个问题。 我有一个非常明显的顺序扫描文件的答案,因为我不擅长DS和Algo。有人可以提供一些有效的查找方法。感谢。
答案 0 :(得分:2)
日志不是在其中存储数据的标准结构。
考虑是否在用户名上发生了异常,它可能有两次或三次打印用户名。在那种情况下,我们无法获得准确的结果。如果某个开发人员使用用户名打印日志以进行澄清,则会破坏整个过程。
建议以SQL等标准格式存储这些内容,以便从中获取数据更容易,更快速和准确。
如果您盲目地考虑需要单独使用用户名,那么它将是普通的文件搜索。
答案 1 :(得分:2)
可以这样做:
首先,将您的所有用户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){}
}
最后,打印一周内登录两次的用户:
for(int k=0;k<user.length;k++){
if(user[k][1].equals("2")){
System.out.println(user[k][0]);
}
答案 2 :(得分:1)
我认为不可能比线性更好,但是,它可能比二次方更好,这是天真的解决方案。您可以逐行扫描文件,您可以在其中为看不见的名称创建新的映射条目,或者增加映射中名称的出现次数。这假设名称是唯一的。最后,在地图上迭代值为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.");
}
}
答案 3 :(得分:1)
众所周知,“Log不是存储数据的标准结构”。 您必须使用纯逻辑来查找登录详细信息。 通过使用错误消息,您必须区分异常和有效的登录详细信息。 如果凭证有效,则递增计数。通过这种方式,只有可以知道..
答案 4 :(得分:1)
假设文件只是每个登录的一行,并且名称是唯一的,那么我会接近它,就像拥有一组访问过两次以上的名称和一个访问时间的名称映射。然后这样做
<强>假设强>
文件数据如下所示(即单行上的唯一名称)
David Tennant
Sarah Jane Smith
Dalek Sec
Emilia Pond
存储在同一目录中的所有文件
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()
答案 5 :(得分:1)
我的建议如下:
为什么这会更快?,因为当应用find_position /或元素时,您只需排除您知道的,不需要的树的部分,因此您根本不检查那里。这是用我们的例子中的compareTo评估的)因此,如果我们想在一百万用户的二叉搜索树中找到用户名为“johnDoe”的用户,首先评估“johndoe”比较用户名为根,我们将排除树的一半,意味着500.000个元素,所以想象我们能够更快地得到所需的结果。
注意:为了使二进制搜索树以最佳方式工作,它应该是平衡的,有实际平衡二叉搜索树的算法和工具。