how to remove duplicate results generating from hashmap - java

I was given a problem - there is a box containing label and has value in it. for example - box with label 'a' contains value 2, box with label 'b' contains value 7 etc. I was asked to find the pairs that adds to sum 10. I wrote below code to find the pair using hashmap. But it contains same result twice with only difference of position of letter.
For example - (a,e) is same as (e,a)
How can I keep/print only the unique pair?
Below is my code :
public class BoxValue {
public void pair()
{
int sum = 10;
HashMap<Integer, Character> m = new HashMap<Integer, Character>();
m.put(2, 'a');
m.put(7, 'b');
m.put(4, 'c');
m.put(3, 'd');
m.put(8, 'e');
m.put(6, 'f');
Set<Integer> s = m.keySet();
for(Integer in : s)
{
if(m.containsKey(sum-in))
System.out.println(m.get(in)+","+m.get(sum-in));
}
}
public static void main(String[] args) {
BoxValue bv = new BoxValue();
bv.pair();
}
}

I would just use a Set to keep track of which complements you've already seen:
Set<Integer> seen = new HashSet<>();
for (Integer in : m.keySet())
{
if(m.containsKey(sum-in) && !seen.contains(in))
{
System.out.println(m.get(in) + "," + m.get(sum-in));
seen.add(sum-in);
}
}
You can do it without any additional storage if you're able to modify the map, at the loss of some clarity:
for (Integer in : m.keySet())
{
if(m.containsKey(sum-in) && m.get(in) != null)
{
System.out.println(m.get(in) + "," + m.get(sum-in));
m.put(sum-in, null);
}
}
Output:
a,e
d,b
c,f

You can use a map for keys
List<Integer> s = new ArrayList<>(m.keySet()); // Create a key list
HashMap<Integer, Boolean> pos = new HashMap<Integer, Boolean>(); // Map for used key
for (int i = 0; i < s.size(); i++) {
if (m.containsKey(sum - s.get(i)) && !pos.containsKey(sum - s.get(i)))
System.out.println(m.get(s.get(i)) + "," + m.get(sum - s.get(i)));
pos.put(s.get(i), true); // Update map
}

Related

How can I add an associated value to a map that already has a key?

I have a Map<Character, String> that already gets a value for the key (Character) based on a for loop. How can I now go through this map and check whether a certain key is in this map (e.g. 'A' or 'a' [because case ignore]) and then add my desired value (e.g. 4) to this key (so that from "A=" becomes an "A=4")?
I hope my problem is clear
Here is my present code:
public static Map<Character, String> replacings(String s) {
Map<Character, String> leetMap = new TreeMap<>();
for(int i = 1; i < s.length(); i++) {
if(s.charAt(i) == '=') {
leetMap.put(s.charAt(i - 1), "");
leetMap.put(s.toLowerCase().charAt(i - 1), "");
}
}
for(int j = 0; j < leetMap.size(); j++) {
//look for the key here and then add a value to it [my problem]
}
return leetMap;
}
My main method until yet (example):
Map<Character, String> mappings = replacings(
"A=4,B=8,E=3,G=6,L=1,O=0,S=5,T=7,Z=2,"
);
So now, I want to add the numbers to the keys.
You can iterate over a map using it's entrySet like this:
for(Map.Entry<Character, String> entry : leetMap.entrySet()) {
if(e.getKey() == 'A') {
//things
}
}
But the real question is why you want this to happen in different loops? Why are you not adding the value to the map at the same time when you add the key?
My attempt looks like this:
private static Map<Character, String> replacings(String s) {
Map<Character, String> leetMap = new TreeMap<>();
String[] splitted = s.split(",");
for (String kv : splitted) {
String[] kvsplit = kv.split("=");
leetMap.put(kvsplit[0].charAt(0), kvsplit[1]);
leetMap.put(kvsplit[0].toLowerCase().charAt(0), kvsplit[1]);
}
return leetMap;
}
this prints:
{A=4, B=8, E=3, G=6, L=1, O=0, S=5, T=7, Z=2, a=4, b=8, e=3, g=6, l=1, o=0, s=5, t=7, z=2}

java- How to find intersection of values in Hashset in loop?

I wrote a program in Java where it retrieves records from a database table and stored them in a hashmap.
The keys and values of them are like the following:
Key(represent words) Values(represent filename)
w1 file1
w2 file1
w3 file2
w4 file1
w5 file2
w6 file1,file2
............
The list goes on and on but this is just an idea of how it looks like.As you can see, there's no duplicate for words and they are unique.
Given that I have this hashmap info,I need to find the intersection of the key and it's next key and return the results of the intersection. The idea looks like this:
w1∩w2= file1
w2∩w3= empty
w3∩w4= empty
........and it keeps going until it reaches the finishes the final pair of keys in the hashmap.
Since the pair of intersection results depends on the number of keys in the hashmap,I am guessing I'll need to use some loop to keep it iterating to return all the results.
Is there a way on how to get the intersection of each subsequent keys and also a way that is optimize regardless the size of the hashmap?
I appreciate any suggestion.
Make a variable that will hold all those intersections. In your loop retrieve 2 keys at a time. Compare each values of the 2 keys and if they are the same add the value to your intersection holder. Repeat the steps until there is no more pairs.
Here is the code.
Add this below your try/catch
LinkedHashmap<String, Set<String>> intersectionMap = new LinkedHashmap<>();
if (map.keySet() != null) {
String[] keys = map.keySet().toArray(new String[map.keySet().size()]);
for (int i = 0; i < keys.length - 1; i++) {
String key1 = keys[i];
String key2 = keys[i + 1];
TreeSet<String> interSection = intersection(map.get(key1), map.get(key2));
intersectionMap.put(key1 + "∩" + key2, interSection);
}
}
Add this helper method. This method will find the intersection of the two sets. This will be the key in solving your problem.
public static TreeSet<String> intersection(TreeSet<String> setA, TreeSet<String> setB) {
// An optimization to iterate over the smaller set
if (setA.size() > setB.size()) {
return intersection(setB, setA);
}
TreeSet<String> results = new TreeSet<>();
for (String element : setA) {
if (setB.contains(element)) {
results.add(element);
}
}
return results;
}
Yet another version with set operations:
Map<String>, Set<String>> intersections(Map<String, TreeSet<String>> map) {
Map<String>, Set<String>> result = new TreeMap<>();
List<String> words = new ArrayList<>(map.keySet());
words.sort();
for (int i = 0; i < words.size() - 1; ++i) {
String wordI = words.get(i);
Set<String> valueI = map.get(wordI);
for (int j = i + 1, j < words.size(); ++j) {
String wordJ = words.get(j);
Set<String> valueJ = map.get(wordJ);
String word = wordi + "∩" + words[j];
Set<String> value = new TreeSet<>(valueI);
value.retainAll(valueJ);
result.put(word, value);
}
}
return result;
}

why is map.get() function null?

My code iterates over a char array (char[] charArray), and finds for the key. The key is then used to find the value in a Map. However, the map.get() function is giving me a null even thought I set it as a value and i am not sure why. Thanks!
parameters for this method are:
LinkedBinaryTree<String> and HashMap<String, Integer>
for (int i = 0; i < charArray.length; i++) {
if (Character.isLetter(charArray[i])) {
// Why is map.get(charArray[i]) null??
String char2String = Character.toString(charArray[i]);
if (map.get(char2String) == null) {
throw new IllegalArgumentException("int is null");
}
int k = map.get(char2String);
charArray[i] = Integer.toString(k).charAt(0);
}
}
This is a testcase i wrote to test the method.
#Test
public void testSubstituteMap() {
LinkedBinaryTree<String> tree2 = Assignment.prefix2tree("- x + 1 + x x");
HashMap<String, Integer> Map = new HashMap<String, Integer>();
Map.put("x", 5);
tree2 = Assignment.substitute(tree2, Map);
LinkedBinaryTree<String> expected = Assignment.prefix2tree("- 5 + 1 + 5 5");
assertEquals(Assignment.tree2prefix(expected), Assignment.tree2prefix(tree2));
}
Which results in:
You are putting String keys and trying to get the same with a char key.
Note that in Java "x" is not equals to 'x'
You can either change your Map to char keys or use String array. Since they are single letters, I suggest to keep them with Char's.

Counting the number of unique values in a vector

I have a method which takes in parameters in the form of a vector from another vector. This vector can be of the size 2, 3 or 4 elements.
I want to count the frequency of every word in that vector. For example, if the vector contained the strings : "hello", "my" , "hello" , I want to output an array that is
[2, 1] where 2 is the frequency of hello and 1 is the frequency of my.
Here is my attempt after reading a few questions on this website:
int vector_length = query.size();
int [] tf_q = new int [vector_length];
int string_seen = 0;
for (int p = 0; p< query.size(); p++)
{
String temp_var = query.get(p);
for (int q = 0; q< query.size(); q++)
{
if (temp_var == query.get(q) )
{
if (string_seen == 0)
{
tf_q[p]++;
string_seen++;
}
else if (string_seen == 1)
{
tf_q[p]++;
string_seen = 0;
query.remove(p);
}
}
}
}
System.out.print(Arrays.toString(tf_q));
What is the right direction to go?
Use a HashMap of type to track the unique string values you encounter that count each word
String[] vector // your vector
Map<String, Integer> stringMap = new HashMap<String, Integer>();
for (int i = 0; i < vector.length; i++) {
if (stringMap.containsKey(vector[i]) {
Integer wordCount = stringMap.get(vector[i]);
stringMap.put(vector[i], new Integer(wordCount + 1));
}
else {
stringMap.put(vector[i], new Integer(1));
}
}
String[] input = {"Hello", "my", "Hello", "apple", "Hello"};
// use hashmap to track the number of strings
HashMap<String, Integer> map = new HashMap<String, Integer>();
// use arraylist to track the sequence of the output
ArrayList<String> list = new ArrayList<String>();
for (String str : input){
if(map.containsKey(str)){
map.put(str, map.get(str)+1);
} else{
map.put(str, 1);
list.add(str); // if the string never occurred before, add it to arraylist
}
}
int[] output = new int[map.size()];
int index = 0;
for (String str : list){
output[index] = map.get(str);
index++;
}
for (int i : output){
System.out.println(i);
}
This should be your answer! Result is in "int[] output"
If you want to maintain the relation between each word and the frequency of that word, then I suggest that you use a HashMap instead. For example:
Map<String,Integer> histogram = new HashMap<String,Integer>();
for (String word : query)
{
Integer count = histogram.get(word);
if (count == null)
histogram.put(word,1);
else
histogram.put(word,count+1);
}
At this point, you can (for example) print each word with the corresponding frequency:
for (String word : histogram.keySet())
System.out.println(word+" "+histogram.get(word));
Or you can obtain an array which contains only the frequencies, if that's all you want:
Integer[] array = histogram.values().toArray(new Integer[histogram.size()]);
Or even a collection, which is just as useful and convenient as any native array:
Collection<Integer> collection = histogram.values();

How to Count Repetition of Words in Array List?

I've these code for searching occurrence in Array-List but my problem is how I can get result
out side of this for loop in integer type cause I need in out side , may be there is another way for finding
occurrence with out using for loop can you help me ?
thank you...
List<String> list = new ArrayList<String>();
list.add("aaa");
list.add("bbb");
list.add("aaa");
Set<String> unique = new HashSet<String>(list);
for (String key : unique) {
int accurNO = Collections.frequency(list, key);
System.out.println(key + ": " accurNO);
}
You should declare a map like Map<String, Integer> countMap = new HashMap<String, Integer>(); before the loop, and populate it within the loop.
Map<String, Integer> countMap = new HashMap<String, Integer>();
for (String key : unique) {
int accurNO = Collections.frequency(list, key);
coutMap.put(key, accurNO);
//...
}
//now you have a map with keys and their frequencies in the list
Set unique = new HashSet(list);
and
Collections.frequency(list, key);
are too much overhead.
Here is how i would do it
List<String> list = new ArrayList<String>();
list.add("aaa");
list.add("bbb");
list.add("aaa");
Map<String, Integer> countMap = new HashMap<>();
for (String word : list) {
Integer count = countMap.get(word);
if(count == null) {
count = 0;
}
countMap.put(word, (count.intValue()+1));
}
System.out.println(countMap.toString());
Output
{aaa=2, bbb=1}
EDIT output one by one: iterate over the set of entries of the map
for(Entry<String, Integer> entry : countMap.entrySet()) {
System.out.println("frequency of '" + entry.getKey() + "' is "
+ entry.getValue());
}
Output
frequency of 'aaa' is 2
frequency of 'bbb' is 1
EDIT 2 No need for looping
String word = null;
Integer frequency = null;
word = "aaa";
frequency = countMap.get(word);
System.out.println("frequency of '" + word + "' is " +
(frequency == null ? 0 : frequency.intValue()));
word = "bbb";
frequency = countMap.get(word);
System.out.println("frequency of '" + word + "' is " +
(frequency == null ? 0 : frequency.intValue()));
word = "foo";
frequency = countMap.get(word);
System.out.println("frequency of '" + word + "' is " +
(frequency == null ? 0 : frequency.intValue()));
Output
frequency of 'aaa' is 2
frequency of 'bbb' is 1
frequency of 'foo' is 0
Note that you will always have a collection and you need extract the count from it for a particular word one way or another.
List<String> list = new ArrayList<String>();
list.add("aaa");
list.add("bbb");
list.add("aaa");
Map<String,Integer> countMap = new HashMap();
Set<String> unique = new HashSet<String>(list);
for (String key : unique) {
int accurNO = Collections.frequency(list, key);
countMap.put(key,accurNO);
System.out.println(key + ": " accurNO);
}
The Map answers work, but you can extend this answer to solve more problems.
You create a class that has the field values you need, and put the class in a List.
import java.util.ArrayList;
import java.util.List;
public class WordCount {
private String word;
private int count;
public WordCount(String word) {
this.word = word;
this.count = 0;
}
public void addCount() {
this.count++;
}
public String getWord() {
return word;
}
public int getCount() {
return count;
}
}
class AccumulateWords {
List<WordCount> list = new ArrayList<WordCount>();
public void run() {
list.add(new WordCount("aaa"));
list.add(new WordCount("bbb"));
list.add(new WordCount("ccc"));
// Check for word occurrences here
for (WordCount wordCount : list) {
int accurNO = wordCount.getCount();
System.out.println(wordCount.getWord() + ": " + accurNO);
}
}
}
I would sort the list first to avoid going thru the whole list with Collections.frequency every time. The code will be longer but much more efficient
List<String> list = new ArrayList<String>();
list.add("aaa");
list.add("bbb");
list.add("aaa");
Map<String, Integer> map = new HashMap<String, Integer>();
Collections.sort(list);
String last = null;
int n = 0;
for (String w : list) {
if (w.equals(last)) {
n++;
} else {
if (last != null) {
map.put(last, n);
}
last = w;
n = 1;
}
}
map.put(last, n);
System.out.println(map);
output
{aaa=2, bbb=1}

Categories