草庐IT

map - PigLatin 映射键值

coder 2024-01-08 原文

我是第一次使用一些 PigLatin 代码,希望能够通过首先将键值生成为字符数组,然后使用该键来访问 map 中的值。例如,categoryIds 是我的 map ,

catIds = foreach filteredContexts generate elementId,SUBSTRING(categoryAndConfidence,0,2) as catId;
categoryNames = foreach catIds generate elementId, categoryIds#catId as catName;

这是我收到的错误: ERROR 1000:解析时出错。在第 28 行第 64 列遇到“”catId“”。 期待其中之一: “无效的” ... ... ... “空”...

我想做的事情是不可能的吗?我是否需要在每次使用 map 时明确说明键值(例如:categoryIds#'51')?

最佳答案

据我所知,Pig 没有提供任何内置的方法来从 map 中获取键值。对于映射字段,您只能使用 SIZE 函数获取其大小,使用 IsEmpty 函数检查它是否为空,或者使用 map_field#'key' 查找给定键的值。

我自己写了一些 UDF 来帮助我更好地处理 map 数据类型。我的一个函数可能对您有用 - MapToBag - 它可以将 map :map[value_type] 转换为包 :bag{:tuple(key:chararray, value:value_type)} 。有了包,你可以得到 key ,或者应用 FLATTEN 操作。

package com.XXX.YYY.ZZZ;

import org.apache.pig.EvalFunc;
import org.apache.pig.FuncSpec;
import org.apache.pig.data.*;
import org.apache.pig.impl.logicalLayer.FrontendException;
import org.apache.pig.impl.logicalLayer.schema.Schema;

import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;

public class MapToBag extends EvalFunc<DataBag> {

    @Override
    public DataBag exec(Tuple input) throws IOException {
        if (input == null || input.size() == 0) {
            return null;
        }

        @SuppressWarnings("unchecked")
        Map<String, Object> map = (Map<String, Object>) input.get(0);
        if (map == null || map.isEmpty()) {
            return null;
        }

        DataBag bag = bagFactory.newDefaultBag();
        for (String key : map.keySet()) {
            Object value = map.get(key);
            Tuple oneKeyTuple = tupleFactory.newTuple(2);
            oneKeyTuple.set(0, key);
            oneKeyTuple.set(1, value);
            bag.add(oneKeyTuple);
        }

        return (bag.size() == 0) ? null : bag;
    }

    @Override
    public Schema outputSchema(Schema input) {
        try {
            Schema innerSchema = new Schema();
            innerSchema.add(new Schema.FieldSchema("key", DataType.CHARARRAY));
            innerSchema.add(getMapValueSchema(input));
            Schema tupleSchema = new Schema(new Schema.FieldSchema(null, innerSchema, DataType.TUPLE));
            return new Schema(new Schema.FieldSchema(null, tupleSchema, DataType.BAG));
        } catch (FrontendException e) {
            return new Schema(new Schema.FieldSchema(null, DataType.BAG));
        }
    }

    protected Schema.FieldSchema getMapValueSchema(Schema input) throws FrontendException {
        if (input == null || input.size() == 0) {
            return null;
        }
        Schema.FieldSchema mapField = input.getField(0);
        if (mapField.type != DataType.MAP) {
            return null;
        }

        Schema valueSchema = mapField.schema;
        if (valueSchema == null || valueSchema.size() == 0) {
            return null;
        }
        Schema.FieldSchema valueField = valueSchema.getField(0);
        valueField.alias = "value";
        return valueField;
    }

    @Override
    public List<FuncSpec> getArgToFuncMapping() throws FrontendException {
        List<FuncSpec> funcList = new ArrayList<FuncSpec>();
        funcList.add(new FuncSpec(this.getClass().getName(), new Schema(new Schema.FieldSchema(null, DataType.MAP))));
        return funcList;
    }

    private static TupleFactory tupleFactory = TupleFactory.getInstance();
    private static BagFactory bagFactory = BagFactory.getInstance();
}

关于map - PigLatin 映射键值,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/10952048/

有关map - PigLatin 映射键值的更多相关文章

  1. ruby - 在 Ruby 中创建按公共(public)键值分组的新哈希 - 2

    假设我有一个在Ruby中看起来像这样的哈希:{:ie0=>"Hi",:ex0=>"Hey",:eg0=>"Howdy",:ie1=>"Hello",:ex1=>"Greetings",:eg1=>"Goodday"}有什么好的方法可以将它变成如下内容:{"0"=>{"ie"=>"Hi","ex"=>"Hey","eg"=>"Howdy"},"1"=>{"ie"=>"Hello","ex"=>"Greetings","eg"=>"Goodday"}} 最佳答案 您要求一个好的方法来做到这一点,所以答案是:一种您或同事可以在六个月后理解

  2. ruby-on-rails - 只有当不是 nil 时才执行映射? - 2

    如果names为nil,则以下中断。我怎样才能让这个map只有在它不是nil时才执行?self.topics=names.split(",").mapdo|n|Topic.where(name:n.strip).first_or_create!end 最佳答案 其他几个选项:选项1(在其上执行map时检查split的结果):names_list=names.try(:split,",")self.topics=names_list.mapdo|n|Topic.where(name:n.strip).first_or_create!e

  3. ruby - 在 ruby​​ 中使用 .try 函数和 .map 函数 - 2

    我需要从json记录中获取一些值并像下面这样提取curr_json_doc['title']['genre'].map{|s|s['name']}.join(',')但对于某些记录,curr_json_doc['title']['genre']可以为空。所以我想对map和join()使用try函数。我试过如下curr_json_doc['title']['genre'].try(:map,{|s|s['name']}).try(:join,(','))但是没用。 最佳答案 你没有正确传递block。block被传递给参数括号外的方法

  4. ruby-on-rails - 数组到 ruby​​ 中键值对的散列 - 2

    从一个返回表中所有值的模型中,我如何将其转换为名称值对的散列{column_value=>column_value}例如[{:id=>1,:name=>'first'},{:id=>2,:name=>'second'},{:id=>3,:name=>'third'}]到(指定:id和:name){'first'=>1,'second'=>2,'third'=>3} 最佳答案 你可以用inject在一行中完成:a=[{:id=>1,:name=>'first'},{:id=>2,:name=>'second'},{:id=>3,:na

  5. ruby - 不能将 `each` 的所有或大多数情况替换为 `map` 吗? - 2

    Enumerable#each和Enumerable#map的区别在于返回的是接收者还是映射后的结果。回到接收者是微不足道的,你通常不需要在each之后继续一个方法链,比如each{...}.another_method(我可能没见过这样的案例。即使你想回到接收者那里,你也可以通过tap来实现)。所以我认为所有或者大部分使用Enumerable#each的情况都可以用Enumerable#map代替。我错了吗?如果我是对的,each的目的是什么?map是否比each慢?编辑:我知道当您对返回值不感兴趣时​​使用each是一种常见的做法。我对这种做法是否存在不感兴趣,但感兴趣的是,除了从

  6. ruby-on-rails - Order Hash 并删除第一个键值对 - 2

    我有一个以时间戳为键的哈希。hash={"2016-05-31T22:30:58+02:00"=>{"path"=>"/","method"=>"GET"},"2016-05-31T22:31:23+02:00"=>{"path"=>"/tour","method"=>"GET"},"2016-05-31T22:31:05+02:00"=>{"path"=>"/contact_us","method"=>"GET"}}我订购了这个系列并得到了第一双这样的:hash.sort_by{|k,_|k}.first.first但是我该如何删除它呢?删除方法requiresyou知道key的准确

  7. ruby - `map` 比 `each` 快吗? - 2

    map遍历数组是否比each更快?两者有速度差异吗?mapresult=arr.map{|a|a+2}每个result=[]arr.eachdo|a|result.push(a+2)end 最佳答案 我认为是的。我试过这个测试require"benchmark"n=10000arr=Array.new(10000,1)Benchmark.bmdo|x|#Mapx.reportdon.timesdoresult=arr.map{|a|a+2}endend#Eachx.reportdon.timesdoresult=[]arr.each

  8. Ruby:映射和注入(inject)之间的区别 - 2

    在此处阅读有关SO的各种解释,它们是这样描述的:map:Themapmethodtakesanenumerableobjectandablock,andrunstheblockforeachelement注入(inject):Injecttakesavalueandablock,anditrunsthatblockonceforeachelementofthelist.希望你明白为什么我觉得它们表面上看起来很相似。我什么时候会选择一个而不是另一个,它们之间有什么明显的区别吗? 最佳答案 如果您认为inject也别名为reduce,这

  9. ruby - 用于 Ruby 哈希的 map_values()? - 2

    我想念Ruby中的Hash方法来仅转换/映射散列值。h={1=>[9,2,3,4],2=>[6],3=>[5,7,1]}h.map_values{|v|v.size}#=>{1=>4,2=>1,3=>3}你如何在Ruby中归档它?更新:我正在寻找map_values()的实现。#moreexamplesh.map_values{|v|v.reduce(0,:+)}#=>{1=>18,2=>6,3=>13}h.map_values(&:min)#=>{1=>2,2=>6,3=>1} 最佳答案 Ruby2.4引入了方法Hash#tran

  10. ruby - 了解 Ruby Enumerable#map(具有更复杂的 block ) - 2

    假设我有一个函数defodd_or_evennifn%2==0return:evenelsereturn:oddendend我有一个简单的可枚举数组simple=[1,2,3,4,5]然后我用我的函数在map中运行它,使用一个do-endblock:simple.mapdo|n|odd_or_even(n)end#=>[:odd,:even,:odd,:even,:odd]如果不首先定义函数,我怎么能做到这一点?例如,#doesnotworksimple.mapdo|n|ifn%2==0return:evenelsereturn:oddendend#Desiredresult:#=>[

随机推荐