Perl哈希增量如何工作?

时间:2017-03-28 16:12:34

标签: perl

我在perl代码中有以下内容:

$art_entities->{$rel_art_path}++;

我看到它是散列的后增量,它是如何工作的?在Java或C#中会有类似的东西吗?

3 个答案:

答案 0 :(得分:3)

如果它不存在,它会在哈希中创建一个元素,然后将其值增加一个 [1]

例如,

document.createElement()

产生

const styles = {
   mobile: './mobile.css',
   desktop: './dekstop.css',
}

function rendetStyleTag(url){
   const style = document.createElement('style');
   style.href = url;
}

function injectStyleTag(tag){
   document.getElementByTag('head').appendChild(tag);
}

function getDevice() {...}

injectStyleTag(renderStyleTag(styles[getDevice()]));

它也可用于过滤掉重复项。例如,

my %counts;
++$counts{$_} for split(//, 'abracadabra');

产生

my %counts = (
   a => 5,
   b => 2,
   c => 1,
   d => 1,
   r => 2,
);

的Perl:

my %seen;
my @uniq = grep !$seen{$_}++, split(//, 'abracadabra');

C#:

my @uniq = qw( a b r c d );

C#:

my %dict;

++$dict{$key};   # $dict{$key}++ in scalar context gets optimized into ++$dict{$key}.

爪哇:

Dictionary<string, int> dict = new Dictionary<string, int>();

int i;
dict.TryGetValue(key, out i);
dict[key] = i+1;
  1. Dictionary<string, int> dict = new Dictionary<string, int>(); if (dict.ContainsKey(key)) ++dict[key]; else dict[key] = 1; 有一些&#34;魔法&#34;行为,如果递增的变量包含一个字符串(例如,将Map<String, Integer> dict = new HashMap<String, Integer>(); Integer i = dict.get(key); if (i == null) { map.put(key, 1); } else { map.put(key, i+1); } 递增到++),但我不认为这里有相关内容。

答案 1 :(得分:2)

++运算符返回值,然后将变量递增1。哈希只是由其关联的字符串键索引的标量值的无序集合;递增散列中的标量与在散列之外递增标量没有什么不同。

以下功能相同:

$hash{foo}++;
$hash_ref->{foo}++;
$foo++;

Perl's auto-increment operator内置了一些额外的魔法,但是:

  

如果增加一个数字变量,或者一直是变量   在数字上下文中使用,您将获得正常的增量。但是,如果   该变量自设置以来仅用于字符串上下文中,   并且其值不是空字符串并与模式匹配   /^[a-zA-Z]*[0-9]*\z/,增量以字符串形式完成,保留   其范围内的每个字符都带有:

print ++($foo = "99");    # prints "100"
print ++($foo = "a0");    # prints "a1"
print ++($foo = "Az");    # prints "Ba"
print ++($foo = "zz");    # prints "aaa" 
     

undef始终被视为数字,特别是在递增之前更改为0(所以   undef值的后增量将返回0而不是。{   undef)。

Java和C#都有增量运算符,但据我所知,它们并不像Perl那样神奇。 Java HashMap提供get()put()方法,因此您无法直接访问基础数据:

map.put(key, map.get(key) + 1);

C#集合使用方括号,因此如果您有Dictionary,例如:

dict["foo"]++;

答案 2 :(得分:-1)

$art_entities->{$rel_art_path}++;

$art_entities是一个变量(标量,请参见前导$符号)。使用箭头语法,它看起来像是一个对象。

$rel_art_path是另一个标量变量。

->{...}从箭头左侧的对象访问字段(箭头右侧,{花括号})。 Perl在访问限制方面做得不多,即没有publicprivateprotected。您可以添加自己的代码来强制private访问(请参阅Perl最佳实践)或使用类Moose之类的类框架。

代码使用$rel_art_path的值作为$art_entities对象中的字段名称。

在Java中,这将通过反射完成:

import java.lang.reflect.Field;

public class SomeClass {
    public static void main(String[] args) throws Exception {
        SomeOtherClass soc = new SomeOtherClass();
        doSomething(soc, "someValue");
        soc.print();
    }

    public static void doSomething(Object art_entities, String rel_art_path)
    throws Exception {
        Class<?> c = art_entities.getClass();
        Field field = c.getDeclaredField(rel_art_path);
        field.setInt(art_entities, field.getInt(art_entities) + 1);
    }
}

class SomeOtherClass {
    public int someValue = 0;

    public void print() {
        System.out.println("my value is " + someValue);
    }
}

(我在Java代码中使用了你的变量名来使它更清楚,哪个对应于哪个。显然它们是Perl样式(使用下划线),而不是Java(驼峰案例)。)

在Java中,这很糟糕,写得很多,在Perl中它很简短而且很正常。