使用数组的第一个元素或者如果object不是数组

时间:2017-06-02 18:41:19

标签: arrays ruby dynamic

假设方法a可以返回数组或单个元素

def a(n)
  if n == 0
    return '0'
  else
    return '1', '2'
  end
end

irb(main):008:0> a(0)
=> "0"
irb(main):009:0> a(1)
=> ["1", "2"]

什么是最好的"红宝石"表达以下内容的方式:

irb(main):013:0> a(0).<???>.to_i
=> 0
irb(main):014:0> a(1).<???>.to_i
=> 1

我正在寻找一种优雅的语法来实现上述目标。我显然可以实现一个函数,它将执行动态类型检查,并将返回输入变量的第一个元素。

4 个答案:

答案 0 :(得分:4)

您可以使用Array()将其转换为数组:

Array(a(n)).first

> Array(["1","2"]).first
 => "1" 
> Array("0").first
 => "0" 

更好的解决方案(如果您控制a(n))将从您的方法返回一致的类型。

答案 1 :(得分:2)

您可以使用array decomposition仅将第一个值分配给变量:

x, = a(0) #=> "0"
x         #=> "0"

x, = a(1) #=> ["1", "2"]
x         #=> "1"

x, = ...相当于x, * = ...(x, *) = ...

或者作为array decomposition的辅助方法(其他链接,此处需要额外的括号):

def first((x, *))
  x
end

first a(0) #=> "0"
first a(1) #=> "1"

另一种方法是yield值:

def a(n)
  if n == 0
    yield '0'
  else
    yield '1', '2'
  end
end

a(0) { |x| x } #=> "0"
a(1) { |x| x } #=> "1"

a(0) { |*args| args } #=> ["0"]
a(1) { |*args| args } #=> ["1", "2"]

这也适用于Enumerator

def a(n)
  return enum_for(:a, n) unless block_given?
  if n == 0
    yield '0'
  else
    yield '1', '2'
  end
end

a(0).next        #=> "0"
a(1).next        #=> ["1", "2"]

a(0).next_values #=> ["0"]
a(1).next_values #=> ["1", "2"]

答案 2 :(得分:1)

虽然我同意所有评论,但这不是一个好主意。

技术上a(n)[0].to_i适用于两种情况

a(0)[0].to_i
#=> 0
a(1)[0].to_i
#=> 1 

String#[]以与Array#[]返回第n个元素相同的方式返回第n个字符。

根据您的示例,即使第一次返回是Fixnum而不是StringFixnum#[]仍然可以工作:)但只是因为0[0]返回的位引用恰好是0

这就是鸭子打字的全部内容,但它有一些警告,例如a(0)要返回2而不是'0',那么你会得到0,例如2[0].to_i #=> 0因为二进制表示是10而你要求最低有效位。 (右起第一个位置)。

由于您可以完全控制a实际上是什么,因此保持a的返回值的一致性更有意义。它还使得记录方法变得更加简单。

def a(n) 
  n == 0 ? ['0'] : ['1','2']
end 

答案 3 :(得分:1)

//Node---
public class BinaryTreeNode<T> {
    private T data;
    private BinaryTreeNode<T> leftNode;
    private BinaryTreeNode<T> rightNode;

public BinaryTreeNode(T data) {
    this.data = data;
    this.leftNode = null;
    this.rightNode = null;
}

public T getData() {
    return data;
}

public void setData(T data) {
    this.data = data;
}

public BinaryTreeNode<T> getLeftNode() {
    return leftNode;
}

public void setLeftNode(BinaryTreeNode<T> leftNode) {
    this.leftNode = leftNode;
}

public BinaryTreeNode<T> getRightNode() {
    return rightNode;
}

public void setRightNode(BinaryTreeNode<T> rightNode) {
    this.rightNode = rightNode;
}
}

//Binary Tree---
public class BinaryTree<T> {
private BinaryTreeNode<T> rootNode;

public BinaryTreeNode<T> getRootNode() {
    return rootNode;
}

public void setRootNode(BinaryTreeNode<T> rootNode) {
    this.rootNode = rootNode;
}

public void insert(T data){
    this.setRootNode(insert(this.getRootNode(), data));
}

private BinaryTreeNode insert(BinaryTreeNode<T> node, T data){
    if(node == null){
        node = new BinaryTreeNode<>(data);
    }else{
        if(node.getLeftNode() == null){
            node.setLeftNode(insert(node.getLeftNode(), data));
        }else if(node.getRightNode() == null){
            node.setRightNode(insert(node.getRightNode(), data));
        } else{
            if(node.getLeftNode().getLeftNode() == null || node.getLeftNode().getRightNode() == null){
                insert(node.getLeftNode(), data);
            }else if(node.getRightNode().getLeftNode() == null || node.getRightNode().getRightNode() == null){
                insert(node.getRightNode(), data);
            }else{
                insert(node.getLeftNode(), data);
            }
        }
    }
    return node;
}
}