【问题标题】:Given an array of increasing integers: How do you return a range for every three or more consecutive integers?给定一个递增整数数组:如何为每三个或更多连续整数返回一个范围?
【发布时间】:2018-01-24 18:20:38
【问题描述】:

鉴于下面的整数数组(列表),我希望提取每个整数,如果三个或更多整数连续上升,我想用“-”替换中间整数来表示一个范围。然后最后将值作为字符串返回。

例如,列表中的前 7 个整数:-6, -3, -2, -1, 0, 1, 3 会变成'-6,-3-1,3'
因为从-3到1的连续整数不止三个。

最终,solution(list) 应该返回以下字符串:"-6,-3-1,3-5,7-11,14,15,17-20"

以其当前形式返回以下字符串:"-6,-3,-2,-1,0,1,3,4,5,7,8,9,10,11,14,15,17,18,19,20" 也就是简单的将数组转换成字符串。

var list = [-6, -3, -2, -1, 0, 1, 3, 4, 5, 7, 8, 9, 10, 11, 14, 15, 17, 18, 19, 20];
solution(list);

function solution(list) {
    final = [];
    range = [];
    while (list.length > 0) {
        take = list.splice(0,1);
        range.push(take); 
        n = 1;
        while (take+n === list[0]) {
            a = list.splice(0,1); 
            range.push(a);
            n++;
        }
        if (range.length >= 3) {
            min = Math.min(range).toString();
            max = Math.max(range).toString();
            final.push(min + "-" + max); 
            range.length = 0;
        } else if (range.length === 2) {
            final.push(range[0].toString());
            final.push(range[1].toString());
            range.length = 0;
        } else if (range.length === 1) {
            final.push(range[0].toString());
            range.length = 0;
        }
    }
    return final.join(",");
}

但是,我能够在 Ruby 中成功获得所需的结果:

list = [-6, -3, -2, -1, 0, 1, 3, 4, 5, 7, 8, 9, 10, 11, 14, 15, 17, 18, 19, 20]

def solution(list)
    final = []
    range = []
    while (list.length > 0) do
        take = list.shift
        range << take 
        n = 1
        while (take+n == list[0]) do
            a = list.slice!(0) 
            range << a
            n +=1
        end
        if (range.length >= 3)
            final << (range.min.to_s + "-" + range.max.to_s) 
            range = []
        elsif (range.length == 2)
            final << range[0]
            final << range[1]
            range = []
        elsif (range.length == 1)
            final << range[0].to_s
            range = []
        end
    end
    return final.join(",")
end

我在 Ruby 中的方法与我的 JavaScript 几乎相同。所以,如果我想知道是否有人可以:

1) 解释为什么这种方法适用于 Ruby,但不适用于 Javascript。即使这是我的一个简单的语法错误,请随时通知我。

2) 我如何才能在 JavaScript 中提取整数并返回正确的范围?

非常感谢您的帮助!谢谢!

【问题讨论】:

  • 您可以使用 Chrome 开发工具中的断点/跟踪来跟踪程序运行时的每个步骤/变量。
  • -3, -2, -1 会返回什么? -3--1 之类的东西?
  • @sagarpandya82:是的。始终按升序排列。
  • @Stefan:我还没有测试过唯一的负整数范围。但我不得不说,是的,那将是理想的。
  • Ruby 解决方案不必啰嗦:list.chunk_while { |b,a| a == b + 1 }.map { |a| a.length &gt;= 3 ? [ a[0], a[-1] ].join('-') : a }.join(',') 工作正常。

标签: javascript arrays ruby


【解决方案1】:

这是一个更好的红宝石解决方案:

list = [-6, -3, -2, -1, 0, 1, 3, 4, 5, 7, 8, 9, 10, 11, 14, 15, 17, 18, 19, 20]

stringified = list.chunk_while{|a, b| a == b - 1}.map do |seq|
#                  ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the core of the solution
  if seq.length > 2 # long enough sequence
    "#{seq.first}-#{seq.last}"
  else
    seq
  end
end.join(', ')

stringified # => "-6, -3-1, 3-5, 7-11, 14, 15, 17-20"

这也应该是您的 javascript 实现的提示。尽可能分离关注点。分块、字符串化、将序列转换为类似范围的字符串:这些都应该是单独的代码片段。如果它们不是全部纠缠在一起,它们就更容易推理。

【讨论】:

  • chunk_while 的文档包含一个类似的示例 :)
  • @Stefan:哦,确实如此。 :)
  • 谢谢塞尔吉奥。也许,如果我先重构我的 Ruby 代码,我可能需要 JavaScript 的解决方案。
  • 这是最好的答案。请注意,OP 的指定结果不包括组之间的空格。显然这很容易解决。
  • 红宝石在这方面的力量:)
【解决方案2】:

Splice 返回一个数组,你必须从返回的数组中取出第一项

take = list.splice(0,1)[0];

另请注意,shift (take = list.shift()) 更适合此操作。

Math.min 不接受数组,您可以使用 apply/call 的解决方法

Math.min.apply(null,range);

在 ES6 中,这可以通过 Math.min(...range) 使用 spread syntax 来完成

最好通过分配一个新数组来清除数组。

range = [];

我显然更喜欢@ninaholz 的函数式和声明式方法这只是为了解释为什么我的代码不起作用

var list = [-6, -3, -2, -1, 0, 1, 3, 4, 5, 7, 8, 9, 10, 11, 14, 15, 17, 18, 19, 20];
console.log(solution(list));

function solution(list) {
  final = [];
  range = [];
  while (list.length > 0) {
         //splice returns array take first item
        take = list.splice(0,1)[0];
        range.push(take); 
        n = 1;
        while (take + n === list[0]) {
              a = list.splice(0,1)[0]; 
              range.push(a);
              n++;
        }
        console.log(range);
        if (range.length >= 3) {
        //Math.min doesnt accept arrays
           min = Math.min.apply(null,range);
           max = Math.max.apply(null,range);
           final.push(min + "-" + max); 
           range = [];
        } else if (range.length === 2) {
                  final.push(range[0]);
                  final.push(range[1]);
                  range = [];
        } else if (range.length === 1) {
                  final.push(range[0]);
                  range = [];
        }
  }
  return final.join(",");
}

【讨论】:

  • 我不知道 Math.min();不接受数组。感谢您清除它!
  • @moveson 问题是为什么移植到 javascript 的 ruby​​ 代码不起作用,据我所知。在我看来,ninaholz 有一个更好的答案 :) 人们再次喜欢保留他们理解的代码
  • @sabithpocker:是的,确实是这个问题:)
  • @moveson:另外,这个答案中没有红宝石 :)
  • 我知道,但由于这是公认的答案,并且它在第一段中显示.splice(0, 1)[0],我认为最好放一个脚注,说明有更简单的修复;)另外,有时 OP 从对自己代码的深入分析中学到的东西比完整的可复制粘贴替换要多,所以我认为这个答案绝对有价值!
【解决方案3】:

在 Javascript 中,您可以使用三遍方法,首先获取分组范围,然后获取数组中的范围,然后加入整个数组。

var array = [-6, -3, -2, -1, 0, 1, 3, 4, 5, 7, 8, 9, 10, 11, 14, 15, 17, 18, 19, 20],
    result = array
        .reduce(function (r, a) {
            var last = r[r.length - 1];
            if (last && last[1] + 1 === a) {
                last[1] = a;
            } else {
                r.push([a, a]);
            }
            return r;
        }, [])
        .reduce(function (r, a) {
            return r.concat(a[0] === a[1] ? a[0] : a[1] - a[0] < 2 ? a : a.join('-'));
        }, [])
        .join();

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

【讨论】:

  • 干净多了。谢谢妮娜!
猜你喜欢
  • 2019-12-07
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-01-29
  • 2015-10-30
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多