多渠道联系人问题:根据信息查找相关工单 问题描述问题数据集

如何解决多渠道联系人问题:根据信息查找相关工单 问题描述问题数据集

问题描述

以下问题描述摘自 Shopee Code League 2021。

对于每个工单,如果每个用户的联系人信息相同,请确定他们的所有联系人。每张票都通过 EmailPhoneOrder ID 直接或间接相关,因此每张票都属于同一用户。例如:

门票 ID 电子邮件 订单 ID 电话 联系人
A 0 john@gmail.com 12345678 不适用 5
B 1 不适用 12345678 682212345 2
C 34567 wick@gmail.com 不适用 682212345 4
D 78999 wick@gmail.com 不适用 不适用 3
  • 票证 A 和 B 通过 Order ID
  • 链接
  • 门票 B 和 C 通过 Phone
  • 链接
  • 门票 C 和 D 通过 Email
  • 链接
  • 门票 A 和 D 通过门票A > B > C > D
  • 间接链接

在本例中,该用户共有 14 个 Contact。此用户的 ticket_trace/contact 对将为 0-1-34567-78999,14

对于每张票,确定属于同一用户的所有其他 ID,按升序排序,以及用户拥有的 Contact 总数。按以下格式生成一个包含 2 列的 csv 文件:

ID ticket_trace 和联系方式
0 0-1-34567-78999,14
1 0-1-34567-78999,14

请注意,有 500,000 行数据。在短时间内最低时间复杂度内存使用解决此问题的最有效方法是什么?

问题数据集

输入文件示例,contacts.json

[
   {
      "Id":0,"Email":"gkzAbIy@qq.com","Phone":"","Contacts":1,"OrderId":""
   },{
      "Id":1,"Email":"","Phone":"329442681752","Contacts":4,"OrderId":"vDDJJcxfLtSfkooPhbYnJdxov"
   },// more data
]

Click here 用于问题数据集和更详细的描述。

解决方法

这是我使用 Python3 的解决方案。我使用了 2 个字典来存储票证连接。第一个字典按值存储连接的票证。第二个字典存储每个 id 连接(跟踪)。最后,使用第二个字典中的跟踪计算联系人。是的,也是一个很慢的方式。它需要3个循环。在 Kaggle 内核中计算所有 500.000 行最多需要 15 秒。

Kaggle kernel

# Import tools
import numpy as np
import pandas as pd

# Load data
df = pd.read_json('/kaggle/input/scl-2021-da/contacts.json')
npdata = df.values

# Initialize memory
memory = {}
connections = {}

# Store connected tickets by value
def add_to_memory(ticket_id,value):
    if value != "":
        if value in memory:
            memory[value].add(ticket_id)
            return
        memory[value] = {ticket_id}

for row in npdata:
    ticket_id = row[0]

    # Order Id
    add_to_memory(ticket_id,row[4])

    # Email
    add_to_memory(ticket_id,row[1])

    # Phone
    add_to_memory(ticket_id,row[2])

# Calculate Trace
for ids in memory.values():
    current_connection = set(ids)

    for uid in ids:
        if uid in connections:
            current_connection.update(connections[uid])

    for uid in current_connection:
        connections[uid] = current_connection

# Calculate contacts and add to list
output = []
for ticket_id,trace in sorted(connections.items()):
    contacts = np.sum(npdata[list(trace),3])
    trace = "-".join([str(_id) for _id in sorted(trace)])
    answer = "{},{}".format(trace,contacts)
    output.append({"ticket_id": ticket_id,"ticket_trace/contact": answer})

# Convert to pandas DataFrame & save to csv
output_df = pd.DataFrame(output)
filename = "output.csv"
output_df.to_csv(filename,index=False)

Reference

,

这是我尝试的解决方案。我没有足够的时间来处理所有 500,000 行。基本上,我遍历数据数组并按顺序比较它们的属性。是的,很慢的方式。

import com.google.gson.Gson;

import java.io.FileReader;
import java.io.PrintWriter;
import java.util.*;

public class Main {
    public static void main(String[] args) throws Exception {
        Gson gson = new Gson();
        Ticket[] tickets = gson.fromJson(new FileReader("contacts.json"),Ticket[].class);

        HashMap<Integer,LinkedList<Integer>> ticketTraceMap = new HashMap<>();
        HashMap<Integer,Integer> sumOfContactsMap = new HashMap<>();
        int commonId = 1; // tickets with same commonId's are related

        for (int i = 0; i < tickets.length; ++i) {
            // assign new commonId and increment it if a particular ticket
            // is not related to other tickets yet
            if (tickets[i].commonId == 0) {
                tickets[i].commonId = commonId;
                ++commonId;
            }
            
            int sumOfContacts = 0;
            LinkedList<Integer> ticketTraceList = new LinkedList<>();
            ticketTraceList.add(Integer.parseInt(tickets[i].getId()));

            // get sum of contacts and ticket trace if present
            if (sumOfContactsMap.get(tickets[i].commonId) != null) {
                sumOfContacts = sumOfContactsMap.get(tickets[i].commonId);
            }

            if (ticketTraceMap.get((tickets[i].commonId)) != null) {
                ticketTraceList = ticketTraceMap.get((tickets[i].commonId));
            }

            for (int j = i + 1; j < tickets.length; ++j) {
                if (tickets[i].equals(tickets[j])) {
                    tickets[j].commonId = tickets[i].commonId; // assign commonId to link related tickets
                    sumOfContacts += Integer.parseInt(tickets[j].getContacts());
                    ticketTraceList.add(Integer.parseInt(tickets[j].getId()));
                }
            }
            ticketTraceMap.put(tickets[i].commonId,ticketTraceList);
            sumOfContactsMap.put(tickets[i].commonId,sumOfContacts);
        }
        // store ticket trace string
        HashMap<Integer,String> ticketTraceStringMap = new HashMap<>();

        for (Map.Entry<Integer,LinkedList<Integer>> entry : ticketTraceMap.entrySet()) {
            Collections.sort(entry.getValue()); // sort ticket trace in ascending order
            StringBuilder sb = new StringBuilder();
            // concatenate ticket trace into a string
            for (Integer integer : entry.getValue()) {
                sb.append(integer).append("-");
            }
            sb.setLength(sb.length() - 1);
            ticketTraceStringMap.put(entry.getKey(),sb.toString());
        }
        // print result to a csv file
        PrintWriter pw = new PrintWriter("result.csv");

        StringBuilder builder = new StringBuilder();
        String columnNamesList = "ticket_id,ticket_trace/contact\n";
        builder.append(columnNamesList);

        for (int i = 0; i < tickets.length; ++i) {
            builder.append(tickets[i].getId()).append(",").append("\"").
                    append(ticketTraceStringMap.get(tickets[i].commonId)).append(",").
                    append(sumOfContactsMap.get((tickets[i].commonId))).append("\"").
                    append('\n');
            pw.write(builder.toString());
            builder.setLength(0);
        }
        pw.close();
    }
}

用于存储票证信息的Java对象:

class Ticket {
    private String Id;
    private String Email;
    private String Phone;
    private String OrderId;
    private String Contacts;
    public int commonId;

    // compare 2 tickets based on email,phone no. and order ID
    @Override
    public boolean equals(Object o) {
        Ticket ticket = (Ticket) o;
        return (!getEmail().equals("") && Objects.equals(getEmail(),ticket.getEmail())) ||
                (!getPhone().equals("") && Objects.equals(getPhone(),ticket.getPhone())) ||
                (!getOrderId().equals("") && Objects.equals(getOrderId(),ticket.getOrderId()));
    }
    // getters and setters
}

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐


依赖报错 idea导入项目后依赖报错,解决方案:https://blog.csdn.net/weixin_42420249/article/details/81191861 依赖版本报错:更换其他版本 无法下载依赖可参考:https://blog.csdn.net/weixin_42628809/a
错误1:代码生成器依赖和mybatis依赖冲突 启动项目时报错如下 2021-12-03 13:33:33.927 ERROR 7228 [ main] o.s.b.d.LoggingFailureAnalysisReporter : *************************** APPL
错误1:gradle项目控制台输出为乱码 # 解决方案:https://blog.csdn.net/weixin_43501566/article/details/112482302 # 在gradle-wrapper.properties 添加以下内容 org.gradle.jvmargs=-Df
错误还原:在查询的过程中,传入的workType为0时,该条件不起作用 &lt;select id=&quot;xxx&quot;&gt; SELECT di.id, di.name, di.work_type, di.updated... &lt;where&gt; &lt;if test=&qu
报错如下,gcc版本太低 ^ server.c:5346:31: 错误:‘struct redisServer’没有名为‘server_cpulist’的成员 redisSetCpuAffinity(server.server_cpulist); ^ server.c: 在函数‘hasActiveC
解决方案1 1、改项目中.idea/workspace.xml配置文件,增加dynamic.classpath参数 2、搜索PropertiesComponent,添加如下 &lt;property name=&quot;dynamic.classpath&quot; value=&quot;tru
删除根组件app.vue中的默认代码后报错:Module Error (from ./node_modules/eslint-loader/index.js): 解决方案:关闭ESlint代码检测,在项目根目录创建vue.config.js,在文件中添加 module.exports = { lin
查看spark默认的python版本 [root@master day27]# pyspark /home/software/spark-2.3.4-bin-hadoop2.7/conf/spark-env.sh: line 2: /usr/local/hadoop/bin/hadoop: No s
使用本地python环境可以成功执行 import pandas as pd import matplotlib.pyplot as plt # 设置字体 plt.rcParams[&#39;font.sans-serif&#39;] = [&#39;SimHei&#39;] # 能正确显示负号 p
错误1:Request method ‘DELETE‘ not supported 错误还原:controller层有一个接口,访问该接口时报错:Request method ‘DELETE‘ not supported 错误原因:没有接收到前端传入的参数,修改为如下 参考 错误2:cannot r
错误1:启动docker镜像时报错:Error response from daemon: driver failed programming external connectivity on endpoint quirky_allen 解决方法:重启docker -&gt; systemctl r
错误1:private field ‘xxx‘ is never assigned 按Altʾnter快捷键,选择第2项 参考:https://blog.csdn.net/shi_hong_fei_hei/article/details/88814070 错误2:启动时报错,不能找到主启动类 #
报错如下,通过源不能下载,最后警告pip需升级版本 Requirement already satisfied: pip in c:\users\ychen\appdata\local\programs\python\python310\lib\site-packages (22.0.4) Coll
错误1:maven打包报错 错误还原:使用maven打包项目时报错如下 [ERROR] Failed to execute goal org.apache.maven.plugins:maven-resources-plugin:3.2.0:resources (default-resources)
错误1:服务调用时报错 服务消费者模块assess通过openFeign调用服务提供者模块hires 如下为服务提供者模块hires的控制层接口 @RestController @RequestMapping(&quot;/hires&quot;) public class FeignControl
错误1:运行项目后报如下错误 解决方案 报错2:Failed to execute goal org.apache.maven.plugins:maven-compiler-plugin:3.8.1:compile (default-compile) on project sb 解决方案:在pom.
参考 错误原因 过滤器或拦截器在生效时,redisTemplate还没有注入 解决方案:在注入容器时就生效 @Component //项目运行时就注入Spring容器 public class RedisBean { @Resource private RedisTemplate&lt;String
使用vite构建项目报错 C:\Users\ychen\work&gt;npm init @vitejs/app @vitejs/create-app is deprecated, use npm init vite instead C:\Users\ychen\AppData\Local\npm-