【问题标题】:Looping through elements in an array and finding how many times it appears and adding each other element and pushing into a new array循环遍历数组中的元素并查找它出现的次数并相互添加元素并推入新数组
【发布时间】:2019-02-22 15:08:52
【问题描述】:

我正在尝试解决一个由三个部分组成的 JavaScript 问题。我在解决第 2 步和第 3 步时遇到问题。这是我在工作中尝试解决的问题。

第 1 步:计算元素 (0) 在数组中出现的次数OK

第2步:从左到右将每个值相加并推送到一个新数组这里有困难

第 3 步:打印带有结果的新数组这里有困难

例如:

let a = [1, 2, 0, 0, 3, 4, 0, 1];
Step 1: 0 // => 3 times
Step 2: [1+2, 0, 3+4, 0, 1];
Step 3: let newArry = [3, 0, 7, 0, 1] // => Resulting array

/* Algorithm exercise:
*
*  Step 1: count how many times an element (0) appears on an array // => 0 appears 3 times
*  Step 2: Add each value that's not (0) from left to right and push to a * *new array
*  Step 3: Resulting array should be: let newArry = [3, 0, 7, 0, 1]
*  Explanation : [1+2, 0, 3+4, 0, 1];
*
*/

// Step 1: 1st try 
let a = [1, 2, 0, 0, 3, 4, 0, 1];
let counts = {};


for (let i=0; i < a.length; i++) {
	let num = a[i];
	console.info(`This is num now: ${num}`);
  
 
 	counts[num] = counts[num] ? counts[num] + 1 : 1;
  
  console.info(`This is counts now after looping # ${i}: ${JSON.stringify(counts, undefined, 2)}`);
}

  console.table(`This is counts now: ${counts[0]}`);


// Step 1: 2nd try
let search = 0;
let occurences = a.filter(value => value === search).length;

console.info(`Found ${search} occuring ${occurences} times`);

【问题讨论】:

  • 这是作业还是什么?
  • 是的,类似的。
  • 你有什么问题?
  • 请不要将您的代码链接到第 3 方网站,因为这些链接会随着时间的推移而失效,然后您的问题对于遇到它的人来说毫无意义。如您所见,您可以在您的问题中创建功能代码 sn-ps。

标签: javascript arrays algorithm


【解决方案1】:

第 1 步:计算元素 (0) 在数组中出现的次数

console.log([1, 2, 0, 0, 3, 4, 0, 1].filter(element =&gt; element===0 ).length);

第 2 步和第 3 步

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

const result = array.reduce((prev, current) => {
  if (current) {
    if (prev[prev.length-1]) prev[prev.length-1]+=current;
    else prev.push(current);
  }
  else if (prev[prev.length-1] || prev.length===0) prev.push(current);
  return prev
}, []);

console.log(result);

【讨论】:

  • @Krzystof 谢谢,你介意向我解释一下,好像我在哪里 5,因为我可能会有点迷路是 current = currentValue(?)prev = new array(?)
  • array.prototype.reduce 方法在数组的每个成员上执行一个 reducer 函数(您提供),从而产生一个输出值。 prev 是 reducer 从之前的索引调用返回的值,current 是当前索引的数组值,所以我要做的是迭代数组,将信息累积到 prev
  • 看起来你的第二个程序为[ 1, 2, 0, 0, 3, 4, 0, 0, 0, 1, 0 ]产生了不正确的结果
【解决方案2】:

在这个答案中,我们将写 puzzle 来像这样工作 -

const q =
  0

puzzle
  ( q
  , [ 1, 2, 0, 0, 3, 4, 0, 1 ]
  , printf (`${q} appeared %s times. The result is %s`)
  )
  // 0 appeared 3 times. The result is 3,0,7,0,1

puzzle
  ( q
  , [ 1, 2, 0, 0, 3, 4, 0, 0, 0, 5, 6, 7, 8, 0 ]
  , printf (`${q} appeared %s times. The result is %s`)
  )
  // 0 appeared 6 times. The result is 3,0,7,0,26,0

puzzle
  ( 5
  , [ 1, 2, 0, 0, 3, 4, 0, 0, 0, 5, 6, 7, 8, 0 ]
  , printf (`5 appeared %s times. The result is %s`)
  )
  // 5 appeared 1 times. The result is 10,5,21

我可以分享这个,因为它可以教给你很多东西,但你的老师不太可能接受;不是因为它是一个糟糕的程序,而是初学者不可能自己编写它。

这个程序的独特之处在于它同时完成所有 3 个步骤,只使用一次通过您的输入数组 -

const None =
  Symbol ('None')

const puzzle = (query, [ a = None, b = None, ...rest ], then) =>
  a === None                     # 1
    ? then (0, [])

  : b === None                   # 2
    ? then
        ( Number (query === a)
        , [ a ]
        )

  : query === a && query === b   # 3
    ? puzzle
        ( query
        , [ b, ...rest ]
        , (count, result) =>
            then
              ( count + 1
              , result
              )
        )

  : query !== a && query !== b   # 4
    ? puzzle
        ( query
        , [ a + b, ...rest ]
        , then
        )

  : puzzle                       # 5
      ( query
      , [ b, ...rest ]
      , (count, result) =>
          then
            ( count + Number (query === a)
            , [ a, ...result ]
            )
      )

puzzle 被定义为使用mathematical induction 的递归函数,我们在其中推断我们以特定方式处理的值。请参考上面编号的 cmets,我们将其分解如下:

  1. (base) 当我们没有a时,表示输入是一个数组;没有什么可以计算,没有要加在一起的值,没有要折叠的重复值。在这种情况下,返回 empty 结果:0 表示计数,[] 表示输出数组。

  2. (inductive: a is not none) 当我们有一个a 但没有b,这意味着我们只剩下一项了; singleton 数组。在这里,我们不能将两个值相加或折叠重复值,因为我们只有 一个 值。在这种情况下,返回 singleton 结果:Number (query === a) 用于计数,它将布尔值转换为数字,以及 singleton 输出数组,[ a ]

  3. (归纳:a 不是 none,b is not none) 当我们有一个 a 和一个 b 时,这意味着我们有足够的值来开始处理我们函数的更复杂的操作。我不想添加与查询匹配的数字,也不想在结果中添加a 如果它是重复的,所以我必须先检查一下。当查询同时匹配a b 时,已找到重复项。在这种情况下,请在没有a 的情况下重复拼图。当我们得到较小拼图的结果时,我们使用count + 1 增加计数,因为我们的查询匹配a。此代码分支处理重复元素的删除,因此没有新内容可添加到输出数组result

  4. (归纳:a 不是 none,b 不是 none,query 不匹配两者) 我们有一个 a 和一个 b 和查询不匹配两者。如果它匹配都不匹配,那么我们知道我们可以将ab 加在一起。在这种情况下,用a + b 重复这个谜题。由于查询也不匹配,我们知道没有要更新的计数。输出数组也没有改变,因为我们创建的新数字可能会在出现在输出之前被添加到更多相邻的元素中。因为countresult在这个代码分支中没有变化,所以直接通过then

  5. (归纳:a 不是 none,b 不是 none,query 匹配 ab 我们有一个 ab 并且我们知道查询匹配一个另一个。哪一个匹配并不重要。无论哪种方式,这些值都不是重复的,不应被删除,也不能将这些值相加。在这种情况下,使用b 重复拼图,如果a 匹配查询,则增加计数,并将a 添加到结果中。这是将值插入输出数组的唯一代码分支。


printf 为演示目的定义为 -

const printf = f =>
  console.log .bind (console, f)

展开下面的sn-p,在自己的浏览器中验证结果-

const printf = f =>
  console.log .bind (console, f)

const None =
  Symbol ('None')

const puzzle = (query, [ a = None, b = None, ...rest ], then) =>
  a === None
    ? then (0, [])

  : b === None
    ? then
        ( Number (query === a)
        , [ a ]
        )
  
  : query === a && query === b
    ? puzzle
        ( query
        , [ b, ...rest ]
        , (count, result) =>
            then (count + 1, result)
        )

  : query !== a && query !== b
    ? puzzle
        ( query
        , [ a + b, ...rest ]
        , then
        )

  : puzzle
      ( query
      , [ b, ...rest ]
      , (count, result) =>
          then
            ( count + Number (query === a)
            , [ a, ...result ]
            )
      )

const q =
  0
  
puzzle
  ( q
  , [ 1, 2, 0, 0, 3, 4, 0, 1 ]
  , printf (`${q} appeared %s times. The result is %s`)
  )
  // 0 appeared 3 times. The result is 3,0,7,0,1

puzzle
  ( q
  , [ 1, 2, 0, 0, 3, 4, 0, 0, 0, 5, 6, 7, 8, 0 ]
  , printf (`${q} appeared %s times. The result is %s`)
  )
  // 0 appeared 6 times. The result is 3,0,7,0,26,0

puzzle
  ( 5
  , [ 1, 2, 0, 0, 3, 4, 0, 0, 0, 5, 6, 7, 8, 0 ]
  , printf (`5 appeared %s times. The result is %s`)
  )
  // 5 appeared 1 times. The result is 10,5,21

【讨论】:

  • 感谢@user633183 非常详细的解释,这是一个非常好的示例和代码,你到底是怎么想出这个的?谢谢
  • 我研究并写了很多关于recursion的文章。该技术通常只使用 2 个案例来教授较小的问题,但由于其复杂性,这个特定问题涉及 5 个案例的归纳推理树。一旦您对 2 个案例的逻辑语句编写得心应手,学习如何支持其他案例就变得更容易了。如果您还有其他问题,请告诉我:D
猜你喜欢
  • 1970-01-01
  • 2020-12-22
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2022-09-30
相关资源
最近更新 更多