根据另一个数据集过滤一个数据集

时间:2019-01-17 22:16:15

标签: python algorithm performance filtering

我有很多用户,他们有喜欢的颜色。我有一个数据集-每个记录都有颜色数据-我想向每个用户发送电子邮件。在每封电子邮件中,用户将根据自己喜欢的颜色看到过滤后的数据,这意味着我需要根据自己喜欢的颜色来过滤此数据集。

例如;用户最喜欢的颜色:
[用户1 :(“绿色”,“黄色”),用户2 :(“绿色,蓝色”),用户3 :(“红色”),用户4 :(“橙色”,“紫色”,“红色”),用户5 :(“蓝色”,“黄色”)...]

如何根据用户喜欢的颜色有效地过滤此数据集?

最直接的方法是在每次迭代中循环浏览用户列表并按当前用户喜欢的颜色过滤数据集。但是,这可能导致对相同或通用颜色的多余查询。因此,如果我有100万用户,那么我将对同一数据集进行100万次查询。

有人可以提出一个使这个过程更加优雅的想法吗?我将使用Python做到这一点,但答案可能与语言无关。

3 个答案:

答案 0 :(得分:0)

由于严格来说这是理论上的(您不提供要使用的技术),因此我将继续通过查询来过滤具有相同匹配选项(颜色)的用户。现在,如果您使用的是.NET,则可以通过SQL查询或LINQ to SQL来完成。如果您可以提供有关使用哪种语言的更多信息,我可以为您提供更具体的答案。

答案 1 :(得分:0)

如果您提供有关所用语言和工具/技术的更多详细信息,将会更好。

问题仅存在于现有数据集的过滤中吗?还是可以更改代码?我有一个想法,是否可以添加一些代码。

我以为我可以解决问题的方法不使用任何工具(例如,使用纯JavaScript)。在这种情况下,我更喜欢有两个表User -> Color(上面已提供)和Color -> User,它们之间具有关系,并立即更新两个表。检查代码段以了解我的意思。

Redis(键值数据库)将是一个很好的选择。

我不能为您提供更多帮助,因为该问题不包含任何技术信息,但我将答案留在这里。也许这会让您想到任何主意:)

var USERS = {DefaultUser: {TestColor: true}};
var COLORS = {TestColor: {DefaultUser: true}};

function addColor (userId, color) {
	if (!COLORS[color]) COLORS[color] = {};
	COLORS[color][userId] = true;

	if (!USERS[userId]) USERS[userId] = {};
	USERS[userId][color] = true;
}

function removeColor (userId, color) {
	if (!COLORS[color]) return;
	delete COLORS[color][userId];

  if (!USERS[userId]) USERS[userId] = {};
	delete USERS[userId][color];
}

function findUsersByColor (color) {
	return Object.keys(COLORS[color] || {});
}

function addColorsToUsers () {
  addColor('User1', 'Green');
  addColor('User1', 'Yellow');
  addColor('User2', 'Green');
  addColor('User2', 'Blue');
  addColor('User3', 'Red');
  addColor('User4', 'Orange');
  addColor('User4', 'Purple');
  addColor('User4', 'Red');
  addColor('User5', 'Blue');
  addColor('User5', 'Yellow');
}

function runJob () {
  console.log('Result: findUsersByColor("Green")', findUsersByColor("Green"))
  removeColor("User1", "Green")
  console.log('Result: findUsersByColor("Green")', findUsersByColor("Green"))
}

addColorsToUsers();
runJob();

答案 2 :(得分:0)

扩展@ jake2389的想法,您可以执行一些技巧。您真正能做的事很大程度上取决于您的数据集有多大以及您可以将其放入内存(或数据库)的次数。提高性能的明显方法是进行缓存。假设您有一个方法getRecordsForColors(colors)进行实际过滤(或对数据库的实际查询)。一些非常幼稚的方法会是这样的(请注意,我没有尝试使用此代码,因此可能会有很多小错误):

cache = dict()

def getRecordsCached(colors):
    global cache
    if colors not in cache:
       records = getRecordsForColors(colors)
       cache[colors] = records
       return records
    else:
       return cache[colors]

此方法的明显缺点是,即使只有1个用户使用了所有颜色组合,您也必须将它们保留在缓存中。

一种更聪明的方法可能是选择一些threshold,例如可以存储以下所有组合的3种颜色:

cache = dict()

def getRecordsCached(colors):
    global cache
    if colors not in cache:
       records = getRecordsForColors(colors)
       if len(colors) < threshold:
          cache[colors] = records
       return records
    else:
       return cache[colors]

这将覆盖大多数用户,而那些罕见的长组合用户将产生一些重复的查询。

显然,您根本不必使用基于dict的天真缓存或内存缓存。您可以将数据缓存在同一个数据库中,也可以使用一些专门用于缓存的数据库,例如Memcached或Redis。另外,也可以使用一些支持LRU缓存或some other replacement police

的专用缓存库来代替长度为colors的形式的阈值。

最后,如果您的逻辑是给定颜色集的结果只是每种颜色结果的并集,则可以尝试通过仅缓存每种颜色的结果来覆盖客户端罕见的大颜色组合,那么如果颜色组合不是直接在缓存中,则可以通过合并每种颜色在缓存结果中的项目来进行计算。