Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/string/5.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
在Java中计算列表中每个唯一元素的关键字密度?_Java_String_Data Structures_Hashmap_Find Occurrences - Fatal编程技术网

在Java中计算列表中每个唯一元素的关键字密度?

在Java中计算列表中每个唯一元素的关键字密度?,java,string,data-structures,hashmap,find-occurrences,Java,String,Data Structures,Hashmap,Find Occurrences,我能够使用以下代码计算文本体的关键字密度: HashMap<String, Integer> frequencies = new HashMap<String, Integer>(); String[] splitTextArr = StringX.splitStrIntoWordsRtrnArr(text); int articleWordCount = splitTextArr.length; for (String splitText : splitTextA

我能够使用以下代码计算文本体的关键字密度:

HashMap<String, Integer> frequencies = new HashMap<String, Integer>();

String[] splitTextArr = StringX.splitStrIntoWordsRtrnArr(text);

int articleWordCount = splitTextArr.length;

for (String splitText : splitTextArr) {


 if (frequencies.containsKey(splitText)) {

    Integer previousInt = frequencies.get(splitText);
    Integer newInt = ++previousInt;
    frequencies.put(splitText, newInt);
    } else {

    frequencies.put(splitText, 1);
    }
}
其中,
表示标题ID(即标题1、标题2等),而
表示实际标题

每个关键字的原始出现次数(降序,不区分大小写)如下所示:

佳能:2 |鼠标:2 |无线:2 |相机:1 |充电器:1 |照片:1 |打印机:1 |陷阱:1

注意:每个关键字在每个标题中只计算一次。因此,尽管关键词canon出现了3次,但由于它在同一个标题(即标题2)中出现了两次,因此只计算了一次

在前面的
地图中
,标题1和标题2中都出现了关键词canon。因为每个标题都需要用一个关键字来表示,所以两个标题都可以用关键字canon来表示。不必包含标题1和标题2中的其他关键字(例如:照片、打印机和照相机),因为每个标题应仅由一个关键字(不多,不少)表示。尽管我们可以选择使用关键字photo和camera(或printer和camera)来表示标题1和标题2,但由于这会增加表示所有标题所需的关键字总数,因此并不需要这样做。换句话说,我们希望用尽可能少的关键字来表示所有标题

重要的部分是提取能够一次“表示”列表中所有标题的最少数量的关键字,并跟踪每个关键字链接到的标题数量和标题ID。如果不是5个标题,而是100个标题的列表,其中关键字照片出现95次(即,比关键字佳能出现的次数多),则关键字照片将用于替换关键字佳能,标题2将由关键字照相机表示

如果两个或多个关键字可以代表相同数量的标题,我们将按字母顺序选择第一个关键字。因此,关键字鼠标将用于表示标题title3和title5,而不是关键字wireless。同样,为了表示标题4,将使用关键字charger,因为字母表中字母C位于字母W之前(这是正确的,即使关键字wireless出现两次,而关键字充电器只出现一次,因为包含关键字wireless的标题3已经由关键字鼠标而不是关键字wireless表示,因此当两个关键字表示相同数量的标题时,我们恢复使用字母表中的第一个关键字)

在前面的5个标题示例中,预期输出的格式如下:

LinkedHashMap<String, LinkedHashMap<Integer, ArrayList<String>> map = new LinkedHashMap<String, LinkedHashMap<Integer, ArrayList<String>>();

LinkedHashMap基本上,您需要创建某种类型的数据结构,在其中您需要跟踪关键字、链接到的标题数量以及与之关联的标题ID;如下所示:

[canon, {2, [ title1, title2 ] } ]
如果是这种情况,至少有两个原因是不好的:

  • 使用计数作为键是错误的,因为计数将对其他元素重复
  • 您可以通过返回给定关键字的标题ID列表的大小或长度来简单地计算计数
  • 我提出的解决方案有两个方面:使用一个类捕获关键字和标题ID映射,然后使用一组映射对象

    班级 使用树形图有必要按照条目的键按自然顺序排列条目

    我创建了这个简单的main方法来演示这个实现

    public static void main (String[] args) {
        List<String> titles = List.of("title2: canon camera canon",
            "title3: wireless mouse",
            "title1: canon photo printer",
            "title4: wireless charger", "title5: mouse trap");
        
        MasterMap mappings = new MasterMap(); // A class wrapping TreeMap<String, KeywordMapping> mappings (the code is shown later on)
        
        for (String title : titles) {
            String[] tokens = title.split(": ");
            Set<String> keywords = new HashSet<>(Arrays.asList(tokens[1].split(" ")));
            for (String keyword : keywords) {
                KeywordMapping km = mappings.get(keyword); // don't create duplicate keyword mapping objects
                if (km == null) {
                    km = new KeywordMapping(keyword, tokens[0]);
                }
                km.addTitleId(tokens[0]);
                km.incrementFrequency(keyword);
                mappings.put(keyword, km); // update existing or new keyword mapping entry
            }
        }
        System.out.println(mappings);
        System.out.println("First entry: " + mappings.firstMapping());
        System.out.println("First title in first entry: " + mappings.firstMapping().getValue().getFirstTitleId());
    }
    
    请注意,即使原始标题列表不是自然顺序,在插入到
    关键字映射
    对象后,支持标题ID列表的集合是如何按顺序排列它们的。这与树映射中条目的打印顺序相同

    最后,每个标题的频率计数只增加一次,因为标题ID列表由
    集合而不是
    列表支持,Java中的集合不允许重复。因此,对于
    标题2:canon camera canon
    这样的情况,关键字
    canon
    只计算一次,因为对于该标题一组关键字只有
    {cannon,camera}

    包装树映射以增加功能
    这是因为与“title3”
    {mouse,wireless}
    相关联的两个关键字具有相同的频率(2),但“mouse”是按字母顺序排列的集合中的第一个关键字。

    通过使用正确的术语引用事物来消除混淆。而不是“first String”和“second String”,将它们分别称为键和值。此外,此解释非常复杂。请尽可能多地对其进行总结。@hfontanez感谢您的建设性反馈!我更新了术语并尝试增强总结。希望它能让事情更清楚一些。没问题。我正在研究解决方案。我应该准备好它如果没有打扰,很快就可以了。:)我发布了我的解决方案。我希望我正确理解了您的要求。@感谢您极其详细和翔实的回复!我认为剩下的唯一要求是删除表示标题的关键字,该标题已经由另一个关键字表示。例如,关键字“photo”应该删除,因为标题1由关键字“canon”表示。同样的想法也适用于关键字“打印机”。仅当关键字表示的标题未由其他关键字表示时,才应将其包含在结果中。。(续)@alpha1我正要发布一个更新,如果你想要更多的“元数据”功能,你应该将映射
    TreeMap
    包装在一个类中,并添加你想要的方法。例如,如果标题ID为
    title2
    ,则
    getKeywordsByTitle(String titleId)
    应返回
    {camera,canon}
    。同样,你应该能够创建另一种方法来减少或细化你的地图与该要求。(续)如果两个或两个以上的关键字可以代表相同的标题(佳能vs照片),我们选择出现的一个
    [canon, {2, [ title1, title2 ] } ]
    
    public class KeywordMapping implements Comparable<KeywordMapping> {
        
        private final String keyword;
        private TreeSet<String> titleIds = new TreeSet<String>();
        private int frequency;
        
        public KeywordMapping(String keyword, String titleId) {
            this.keyword = keyword;
            titleIds.add(titleId);
        }
        
        public String getKeyword () {
            return keyword;
        }
        
        public int getTitleCount () {
            return titleIds.size();
        }
        
        public void addTitleId (String titleId) {
            titleIds.add(titleId);
        }
        
        public String getFirstTitleId () {
            return titleIds.first();
        }
        
        public void incrementFrequency(String keyword) {
            if (this.keyword.equals(keyword)) {
                frequency++;            
            }
        }
    
        public int getFrequency() {
            return frequency;
        }
    
        public boolean containsTitle(String titleId) {
            return titleIds.contains(titleId);
        }
    
        @Override
        public int hashCode () {
            final int prime = 31;
            int result = 1;
            result = prime * result + ( (keyword == null) ? 0 : keyword.hashCode());
            result = prime * result + ( (titleIds == null) ? 0 : titleIds.hashCode());
            return result;
        }
    
        @Override
        public boolean equals (Object obj) {
            if (this == obj) return true;
            if (obj == null) return false;
            if (getClass() != obj.getClass()) return false;
            KeywordMapping other = (KeywordMapping) obj;
            if (keyword == null) {
                if (other.keyword != null) return false;
            } else if (!keyword.equals(other.keyword)) return false;
            if (titleIds == null) {
                if (other.titleIds != null) return false;
            } else if (!titleIds.equals(other.titleIds)) return false;
            return true;
        }
    
        @Override
        public String toString () {
            return "KeywordMapping [keyword=" + keyword + ", titleIds=" + titleIds + ", frequency=" + frequency
                + "]\n";
        }
    
        @Override
        public int compareTo (KeywordMapping o) {
            return COMPARATOR.compare(this, o);
        }
    
        private static final Comparator<KeywordMapping> COMPARATOR =
            Comparator.comparing( (KeywordMapping keyMapping) -> keyMapping.keyword);
    }
    
    TreeMap<String, KeywordMapping> mappings = new TreeMap<>();
    
    public static void main (String[] args) {
        List<String> titles = List.of("title2: canon camera canon",
            "title3: wireless mouse",
            "title1: canon photo printer",
            "title4: wireless charger", "title5: mouse trap");
        
        MasterMap mappings = new MasterMap(); // A class wrapping TreeMap<String, KeywordMapping> mappings (the code is shown later on)
        
        for (String title : titles) {
            String[] tokens = title.split(": ");
            Set<String> keywords = new HashSet<>(Arrays.asList(tokens[1].split(" ")));
            for (String keyword : keywords) {
                KeywordMapping km = mappings.get(keyword); // don't create duplicate keyword mapping objects
                if (km == null) {
                    km = new KeywordMapping(keyword, tokens[0]);
                }
                km.addTitleId(tokens[0]);
                km.incrementFrequency(keyword);
                mappings.put(keyword, km); // update existing or new keyword mapping entry
            }
        }
        System.out.println(mappings);
        System.out.println("First entry: " + mappings.firstMapping());
        System.out.println("First title in first entry: " + mappings.firstMapping().getValue().getFirstTitleId());
    }
    
    camera=KeywordMapping [keyword=camera, titleIds=[title2], frequency=1]
    canon=KeywordMapping [keyword=canon, titleIds=[title1, title2], frequency=2]
    charger=KeywordMapping [keyword=charger, titleIds=[title4], frequency=1]
    mouse=KeywordMapping [keyword=mouse, titleIds=[title3, title5], frequency=2]
    photo=KeywordMapping [keyword=photo, titleIds=[title1], frequency=1]
    printer=KeywordMapping [keyword=printer, titleIds=[title1], frequency=1]
    trap=KeywordMapping [keyword=trap, titleIds=[title5], frequency=1]
    wireless=KeywordMapping [keyword=wireless, titleIds=[title3, title4], frequency=2]
    
    First entry: camera=KeywordMapping [keyword=camera, titleIds=[title2], frequency=1]
    First title in first entry: title2
    
    public class MasterMap {
        private TreeMap<String, KeywordMapping> mappings = new TreeMap<>();
        
        public KeywordMapping put(String key, KeywordMapping value) {
            return mappings.put(key, value);
        }
        
        public KeywordMapping get(String key) {
            return mappings.get(key);
        }
        
        public KeywordMapping firstMapping() {
            return mappings.firstEntry().getValue();
        }
        
        public String getKeywordForTitle (String titleId) {
            
            List<KeywordMapping> keywords = new ArrayList<>();
            
            Collection<KeywordMapping> values = mappings.values();
            Iterator<KeywordMapping> iter = values.iterator();
            
            while (iter.hasNext()) {
                KeywordMapping value = iter.next();
                if (value.containsTitle(titleId)) {
                    keywords.add(value);
                }
            }
            
            KeywordMapping temp = keywords.stream()
                .max(Comparator.comparingInt(KeywordMapping::getFrequency)
                    .thenComparing(KeywordMapping::getKeyword).reversed())
                .get();
            
            return temp.getKeyword();
        }
    }
    
    Keyword for title3: mouse