Java算法:按多个案例标准配对列表条目

时间:2012-09-30 11:54:45

标签: java algorithm list

我担心这不是一个简单的问题。很长一段时间以来我一直在考虑解决这个问题的正确方法,并希望一大堆新脑能更好地了解这个问题 - 让我们来看看它:

数据

我们在这里使用的是一个包含多个列的csv文件,这个问题的相关内容是:

  • 用户ID(整数,范围从3到8位,存在多个具有相同UserID的条目) LIST已被此分类
  • 查询(字符串)
  • Epoc(长,epoc时间值)
  • clickurl(String)

我们在这里使用的数据中的每个条目都有这些属性的!null值。

示例数据:

SID,UID,query,rawdate,timestamp,timegap,epoc,lengthwords,lengthchars,rank,clickurl
5,142,westchester.gov,2006-03-20 03:55:57,Mon Mar 20 03:55:57 CET 2006,0,1142823357504,1,15,1,http://www.westchestergov.com
10,142,207 ad2d 530,2006-04-08 01:31:14,Sat Apr 08 01:31:14 CEST 2006,10000,1144452674507,3,12,1,http://www.courts.state.ny.us
11,142,vera.org,2006-04-08 08:38:42,Sat Apr 08 08:38:42 CEST 2006,11000,1144478322507,1,8,1,http://www.vera.org

注意:有多个条目对“Epoc”具有相同的值,这是由于用于收集数据的工具

注2:该列表的大小约为700000,只是fyi

目标:匹配具有相同查询的条目对

范围:共享相同UserID的条目

由于数据收集过程中提到的异常,必须考虑以下因素:

如果两个条目共享“Query”和“Epoc”的相同值,则必须检查列表中的以下元素是否符合这些条件,直到下一个条目对其中一个属性具有不同的值。共享相同Query和Epoc值的条目组将被视为-one-entry,因此为了匹配一对,必须找到与“Query”值匹配的另一个条目。由于缺少更好的名称,让我们称一个共享相同Query和Epoc值的组'chain'

现在已经出局了,它变得容易一些,我们可以从中得到3种类型的对合成:

  1. 进入&条目
  2. 进入&链
  3. Chain&链
  4. 此处的类型1仅表示列表中的两个条目共享“查询”的相同值,但不包含“Epoc”。

    所以这总结了 Equal Query Pairs

    还有不同查询对的情况,可以描述如下:

    在我们匹配相等的查询对之后,有可能存在未与其他条目配对的条目,因为它们的查询不匹配 - 因为这是其中一部分未与另一条目匹配的条目集合称为“不同查询”

    此集合的成员必须在不遵循任何标准的情况下进行配对,但链仍然被视为该对的一个条目。

    对于一般匹配对,可能没有冗余对 - 单个条目可以是n对中的一部分,但是两个单独的条目只能形成一对。

    实施例

    以下条目将配对

    UID,Query,Epoc,Clickurl
    772,Donuts,1141394053510,https://www.dunkindonuts.com/dunkindonuts/en.html
    772,Donuts,1141394053510,https://www.dunkindonuts.com/dunkindonuts/en.html
    772,Donuts,1141394053510,https://www.dunkindonuts.com/dunkindonuts/en.html
    772,raspberry pi,1141394164710,http://www.raspberrypi.org/
    772,stackoverflow,1141394274810,http://en.wikipedia.org/wiki/Buffer_overflow
    772,stackoverflow,1141394274850,http://www.stackoverflow.com
    772,tall women,1141394275921,http://www.tallwomen.org/
    772,raspberry pi,1141394277991,http://www.raspberrypi.org/
    772,Donuts,114139427999,http://de.wikipedia.org/wiki/Donut
    772,stackoverflow,1141394279999,http://www.stackoverflow.com
    772,something,1141399299991,http:/something.else/something/
    

    在这个例子中,甜甜圈是一个链,因此对是(没有标题的亚麻):

    • 平等查询对:(1-3,9)(4,8)(5,6)(5,10)(6,10)
    • 不同的查询对:(7,11)

    My -failed-解决问题的方法:

    我为解决这个问题而开发的算法如下:

    迭代条目列表,直到UserID的值发生变化。

    然后,应用于一个单独的列表,该列表仅包含共享相同UserID的刚刚迭代的元素:

       for (int i = 0; i < list.size(); i++) {
                Entry tempI = list.get(i);
                Boolean iMatched = false;
                //boolean to save whether or not c1 is set
                Boolean c1done = false;
                Boolean c2done = false;
    
            //Hashsets holding the clickurl values of the entries that form a pair
            HashSet<String> c1 = null;
            HashSet<String> c2 = null;
    
            for (int j = i + 1; j < list.size(); j++) {
                Entry tempJ = list.get(j);
                // Queries match
                if (tempI.getQuery().equals(tempJ.getQuery())) {
                    // wheter or not Entry at position i has been matched or not
                    if (!iMatched) {
                        iMatched = true;
                    }
                    HashSet<String> e1 = new HashSet<String>();
                    HashSet<String> e2 = new HashSet<String>();
                    int k = 0;
                    // Times match
                    HashSet<String> chainset = new HashSet<String>();
                    if (tempI.getEpoc() == tempJ.getEpoc()) {
                        chainset.add(tempI.getClickurl());
                        chainset.add(tempJ.getClickurl());
                    } else {
                        e1.add(tempI.getClickurl());
                        if (c1 == null) {
                            c1 = e1;
                            c1done = true;
                        } else {
                            if (c2 == null) {
                                c2 = e1;
                                c2done = true;
                            }
                        }
                    }
                    //check how far the chain goes and get their entries
                    if ((j + 1) < list.size()) {
                        Entry tempjj = list.get(j + 1);
                        if (tempjj.getEpoc() == tempJ.getEpoc()) {
                            k = j + 1;
                            //search for the end of the chain
                            while ((k < list.size())
                                    && (tempJ.getQuery().equals(list.get(k)
                                            .getQuery()))
                                    && (tempJ.getEpoc() == list.get(k).getEpoc())) {
    
                                chainset.add(tempJ.getClickurl());
                                chainset.add(list.get(k).getClickurl());
                                k++;
    
                            }
                            j = k + 1; //continue the iteration at the end of the chain
                            if (c1 == null) {
                                c1 = chainset;
                                c1done = true;
                            } else {
                                if (c2 == null) {
                                    c2 = chainset;
                                    c2done = true;
                                }
                            }
    
                            // Times don't match
                        }
                    } else {
                        e2.add(tempJ.getClickurl());
                        if (c1 == null) {
                            c1 = e2;
                            c1done = true;
                        } else {
                            if (c2 == null) {
                                c2 = e2;
                                c2done = true;
                            }
                        }
                    }
    
                    /** Block that compares the clicks in the Hashsets and computes the resulting data
                    *  left out for now to not make this any more complicated than it already is
                    **/
    
                    // Queries don't match
                } else {
                    if (!dq.contains(tempJ)) { //note: dq is an ArrayList holding the entries of the differen query set
                        dq.add(tempJ);
                    }
                }
    
                if (j == al.size() - 1) {
                    if (!iMatched) {
                        dq.add(tempI);
                    }
                }
            }
            if (dq.size() >= 2) {
    
                for (int z = 0; z < dq.size() - 1; z++) {
                    if (dq.get(z + 1) != null) {
                        /** Filler, iterate dq just like the normal list with two loops
                        *
                        **/
                    }
                }
            }
    
        }
    

    所以,使用过多的循环我会尝试匹配这些对,导致一个非常长的运行时间到目前为止我还没有看到

    好的,我希望我没有忘记任何重要的事情,我稍后会添加更多所需的信息 如果你已经做到这一点,感谢阅读 - 希望你有一个可能对我有帮助的想法

2 个答案:

答案 0 :(得分:1)

使用SQL将数据导入数据库,然后执行查询。你的txt文件太大了;难怪通过它需要很长时间。 :)

答案 1 :(得分:0)

首先,从每个链中删除除一个条目以外的所有条目。为此,请按(userid,query,epoch)排序,删除重复项。

然后,扫描已排序的列表。获取(userid,query)对的所有条目。如果只有一个,将其保存在列表中以供以后处理,否则发出所有对。

对于您保存以供以后处理的给定用户的所有条目(这些是类型2和3),发出对。