有没有嵌套函数可以用来获取二维数组中对的出现次数?

huangapple go评论70阅读模式
英文:

Is there a nested function I can use to fetch occurrences of pairs in a 2-D array?

问题

for i in range(10):
  for j in range(10):
    count = 0
    for record in arr:
      if i in record and j in record:
        count += 1
    result[i][j] = count
英文:

Here is what I am trying to do:

I have 2 million records and each record is an array of 4 elements consisting of codes from 1 to 9. so the input looks like

arr = [
  [1, 2, 0, 3],
  [3, 1, 4, 0],
];

I want my function to return a table that find the number of occurance of each pair,

result [0,1] = 2 , since 0 and 1 both occurs together in each of the two record

similarly,
result [1,3] = 2, and result [1,4] = 1 (since it only occurs together in 1 row)

Here is what I have tried so far,

for (i = 0; i <= 9; i++) {
  for (j = 0; j <= 9; j++) {
    count = 0;
    for (k = 0; k <= 3; k++) {
      for (l = 0; l <= 3; l++) {
        if (arr[j][k].includes(i, j)) {
          count++;
        }
      }
    }
    result[i][j] = count;
  }
}

This seems awefully inefficient with n^4 complexity and I was wondering I could seek some guidance on how to pursue this. Thanks in advance.

答案1

得分: 0

在Python中的示例解决方案:

def func(nums: List[int], data: List[List[int]]) -> int:
    num_1, num_2 = nums
    count = 0
    for slice in data:
        if num_1 in slice and num_2 in slice:
            count += 1
    return count

用法:

arr = [[1, 2, 0, 3],
       [3, 1, 4, 0]]

print(func([0, 1], arr))

2

英文:

Sample solution in Python:

def func(nums: List[int], data: List[List[int]]) -> int:
    num_1, num_2 = nums
    count = 0
    for slice in data:
        if num_1 in slice and num_2 in slice:
            count += 1
    return count

Usage:

arr = [[1, 2, 0, 3],
       [3, 1, 4, 0]]

print(func([0, 1], arr))

2

答案2

得分: 0

首先,你的代码中没有n^4的复杂度。实际上,由于你的代码似乎有硬编码的循环边界(93),它是一个固定时间块,O(1)。假设你想对你的两百万条记录运行某些操作,并且希望每个操作都能相对快速。

首先,你需要一种方法来测试每个45对 [0, 1]、[0, 2]、[0, 3]、...、[8, 8]、[8, 9] 是否与你的每一条记录相匹配,并在此过程中累积结果。我们可以使用双重reduce来实现这一点,像这样:

const pairs = ([n, ...ns]) =>
  n == undefined || ns.length == 0
    ? []
    : [...ns.map(m => [n, m]), ...pairs(ns)];

const countPairs = (arr, ps = pairs([...'0123456789']).map(([a, b]) => `${a}${b}`)) =>
  Object.entries(
    arr.map(ar => new Set(ar.map(String))).reduce(
      (a, s) =>
        ps.reduce((a, p) => ((a[p] += s.has(p[0]) && s.has(p[1]) ? 1 : 0), a),
        a),
      Object.fromEntries(ps.map(p => [p, 0]))
    )
  ) /*.filter(([k, v]) => v !== 0)*/ .map(
    ([k, count]) => ({ pair: k.split('' ).map(Number), count })
  );

const arr = [[1, 2, 0, 3], [3, 1, 4, 0]];

console.log(countPairs(arr));

如果只想要具有正数计数的对(这可能对于两百万条记录来说可能不太相关,具体取决于你的数据),那么取消注释对.filter的调用。

我们首先使用一个简单的递归辅助函数pairs,通过一个示例应该很容易理解:

pairs(['a', 'b', 'c', 'd'])
//=> [['a', 'b'], ['a', 'c'], ['a', 'd'], ['b', 'c'], ['b', 'd'], ['c', 'd']]

我们的主要函数首先在[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]上调用pairs,将生成的对组合成字符串([2, 7] //=> '27')。然后,它将每个你的两百万条记录转换为数字集合(这应该比Array.includes具有更快的查找速度,尽管我没有测试,而且对于只有四个元素的数组可能不太有帮助)。

接下来,我们在这些新集合上进行减少,对于每个集合,我们在字符串化的对上减少,并在两个级别上累积到一个对象中,该对象最初看起来像这样:{'01': 0, '02': 0, '03': 0, /*...*/, '88': 0, '89': 0},在当前集合中包含两个数字的每对中添加1

我不确定你希望如何格式化结果。我选择使用Object.entries,一个可选的.filter调用以及一个map,将其转换成类似这样的形式:

[
  { pair: [1, 2], count: 1 },
  { pair: [1, 3], count: 2 },
  { pair: [1, 4], count: 1 },
  { pair: [2, 3], count: 1 },
  { pair: [3, 4], count: 1 },
  { pair: [0, 1], count: 2 },
  { pair: [0, 2], count: 1 },
  { pair: [0, 3], count: 2 },
  { pair: [0, 4], count: 1 },
]

(取消注释.filter调用),但你可以根据需要重新格式化。

英文:

First off, you do not have any n^4 complexity in there. In fact, as your code seems to have hard-coded loop boundaries (9, and 3), yours is a fixed-time block, O(1). Presumably you want to run something over your two million records, and want something that will be reasonably fast for each.

Well, first of all, you need a way to test each of the 45 pairs,[0, 1], [0, 2], [0, 3], ..., [8, 8], [8, 9] against every one of your records, accumulating a result as you go. This we can do with a double reduce, like this:

<!-- begin snippet: js hide: false console: true babel: false -->

<!-- language: lang-js -->

const pairs = ([n, ...ns]) =&gt;
  n == undefined || ns .length == 0
    ? []
    : [...ns .map (m =&gt; [n, m]), ...pairs (ns)]

const countPairs = (arr, ps = pairs ([...&#39;0123456789&#39;]) .map (([a, b]) =&gt; `${a}${b}`)) =&gt; 
  Object .entries (arr .map (ar =&gt; new Set (ar .map (String))) .reduce (
    (a, s) =&gt; ps .reduce ((a, p) =&gt; ((a

+= s .has (p [0]) &amp;&amp; s .has (p [1]) ? 1 : 0), a), a), Object .fromEntries (ps .map ((p) =&gt;

)) )) /*.filter (([k, v]) =&gt; v !== 0)*/ .map ( ([k, count]) =&gt; ({pair: k .split (&#39;&#39;) .map (Number), count}) ) const arr = [[1, 2, 0, 3], [3, 1, 4, 0]] console .log (countPairs (arr))

<!-- language: lang-css -->

.as-console-wrapper {max-height: 100% !important; top: 0}

<!-- end snippet -->

If you only want the pairs with positive counts (this might not be particularly relevant for two million records, depending upon your data), then uncomment the call to .filter.

We start with a simple recursive helper, pairs, which should be clear enough with an example:

pairs ([&#39;a&#39;, &#39;b&#39;, &#39;c&#39;, &#39;d&#39;])
//=&gt; [[&quot;a&quot;, &quot;b&quot;], [&quot;a&quot;, &quot;c&quot;], [&quot;a&quot;, &quot;d&quot;], [&quot;b&quot;, &quot;c&quot;], [&quot;b&quot;, &quot;d&quot;], [&quot;c&quot;, &quot;d&quot;]]

Our main function first calls pairs on [0, 1, 2, 3, 4, 5, 6, 7, 8, 9], combines the resulting pairs into strings ([2, 7] //=&gt; &#39;27&#39;). Then it converts each of your two million records into Sets of numbers (which should have faster lookup than Array .includes, although I didn't test, and it's possibly not helpful for arrays only four elements long.)

Then we reduce over these new Sets, for each one reducing over the stringified pairs, and accumulating at both levels to an object that initially looks like {&#39;01&#39;: 0, &#39;02&#39;: 0, &#39;03&#39;: 0, /*...*/, &#39;88&#39;: 0, &#39;89&#39;: 0}, adding 1 to every pair where both digits are in the current set.

I'm not sure how you wanted your results formatted. I chose to use Object.entries, an optional filter call, and a map to turn this into something like this:

[
  {pair: [1, 2], count: 1}
  {pair: [1, 3], count: 2}
  {pair: [1, 4], count: 1}
  {pair: [2, 3], count: 1}
  {pair: [3, 4], count: 1}
  {pair: [0, 1], count: 2}
  {pair: [0, 2], count: 1}
  {pair: [0, 3], count: 2}
  {pair: [0, 4], count: 1}
]

(with the .filter call uncommented) but you could reformat how you like.

huangapple
  • 本文由 发表于 2023年3月7日 11:09:58
  • 转载请务必保留本文链接:https://go.coder-hub.com/75657706.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定