Map Support in Shell Scripting - shell

I am new in Shell Scripting, however i am friendly with Java Maps. I Just wanted to know that how can i use Map facility in Shell Scripting. Below is the facility i need to use in shell-
HashMap<String, ArrayList<String>> users = new HashMap<String, ArrayList<String>>();
String username = "test_user1";
String address = "test_user1_address";
String emailId = "test_user1_emailId";
ArrayList<String> values = new ArrayList<String>();
values.add(address);
values.add(emailId);
users.put(username, values);
String anotherUser = "test_user2";
if (users.containsKey(anotherUser)) {
System.out.println("Do some stuff here");
}
In short, i want to use a Map, which has String as key, either Vector or ArrayList as value (otherwise i have live with Arrays instead of ArrayList and manually take care of indexes) , put method to insert and one more method to check the presence of the key in the existing Map.
The above code is a sample code.
Thank you in advance.

bash does not support nested structures like this. Either use separate variables for each array, or use something more capable such as Python.

Related

Trie with association between words

I have a usecase where i want to correct words.
I have set of correct and incorrect words[spelling mistake].
I populate the trie with all words.
i have both the correct and incorrect version of every word.
Now in case if i get word as "a" for correction ,
-- i search it in trie.if trie has this word , i want to associate this word with the correct version of this word.
Solution :
i can set correct version ["a1"] of word at last node of incorrect word in trie. And can resolve it to "a1" .
But i have to store correct version of each word at last node that will increase the memory foot print .
Since i have all words loaded in to trie [correct/incorrect].
Is there any way i can make association between correct and incorrect word without again storing entire word in last node as value ?
Any pointer ?
public class TrieNode<T> {
private Map<Character, TrieNode<T>> childs;
private boolean complete;
private T value;
....
}
You could use a single dictionary for this. In C#, that would be:
Dictionary<string, string> MisspellingsLookup = new Dictionary<string, int>();
The key is the misspelling, and the value is the correct spelling.
Now, some words are commonly misspelled in multiple ways. For example, "occasion" is often misspelled as "ocassion" or "occassion" If you want to reduce the memory used by the multiple misspellings, you can use a temporary dictionary during construction. Whenever you add a misspelling, you look up the correct spelling in the good words dictionary, and if it's already there then you use that value. So all you do is store a reference to an existing word rather than creating a new string. Here's an example:
Dictionary<string, string> GoodWords = new Dictionary<string, int>();
Dictionary<string, string> Misspellings = new Dictionary<string, string>();
void AddMisspelling(string misspelled, string correct)
{
string goodWord;
if (!GoodWords.TryGetValue(correct, out goodWord))
{
goodWord = correct;
GoodWords.Add(correct, correct);
}
// Always use goodWord here, so you're not creating duplicate strings.
Misspellings.Add(misspelled, goodWord);
}
When you're done adding words, you can clear the GoodWords dictionary to save space:
GoodWords = null;
I recommend a dictionary here because it'll almost certainly use less memory, and lookup is O(1) rather than O(word length).

Combining Multiple Maps together in Pig

I am using pig for the first time. I've gotten to the point where I have exactly the answer I want, but in a weirdly nested format:
{(price,49),(manages,"1d74426f-2b0a-4777-ac1b-042268cab09c")}
I'd like the output to be a single map, without any wrapping:
[price#49, manages#"1d74426f-2b0a-4777-ac1b-042268cab09c"]
I've managed to use TOMAP to get this far, but I can't figure out how to merge and flatten it away.
{([price_specification#{"amount":49,"currency":"USD"}]),([manages#"newest-nodes/1d74426f-2b0a-4777-ac1b-042268cab09c"])}
How should I be going about this?
Unfortunately, there are no built-in functions to do this for you. You'll have to write your own UDF. Fortunately, this is a simple one.
The exec method would just go something like:
public Map<String, Object> exec(Tuple input) {
Map<String, Object> m = new HashMap<String, Object>();
for (int i = 0; i < input.size(); i++)
m.putAll((Map<String, Object>) input.get(i));
return m;
}
The UDF could take any number of maps as arguments.
Note that if two or more maps share a key, then the final one encountered will be the one that is kept and the others get overwritten.

Spring Batch Passing list of values as a parameter

I want to pass list of id's as one of parameter to Spring batch. Is this possible to achieve?
Thanks in advance.
What you are trying to do is not possible.
From the JobParameter doc:
Domain representation of a parameter to a batch job. Only the
following types can be parameters: String, Long, Date, and Double. The
identifying flag is used to indicate if the parameter is to be used as
part of the identification of a job instance.
You might be tempted write your list of of id's to a comma delimited string and pass that as a single parameter but beware that when stored in the DB it has a length of at most 250 bytes. You'll either have to increase that limit or use another way.
Perhaps you can explain what why you need to pass that list of ids.
If you want to pass the list from ItemReader, then you have to get JobParameters first (you have to declare your reader to be step scoped for that, see this thread also).
You will have to put your list as a parameter to the JobParameters. As JobParameters is immutable, you will have to create a new object then
List yourList = ....
JobParameters jp = (JobParameters) fac.getBean("params");
Map map=params.getParameters();
map.put("yourList", list);
params=new JobParameters(map);
launcher.run(job, params);
You cannot use the List<T> concept itself in spring-batch, but I think you can implement your intentions(listOf(a, b, c, d..)) in the following way.
The job parameter itself receives a comma-separated string of items.
#Nonnull
private List<String> someList = Collections.emptyList();
#Value("#{jobParameters['someList']}")
public void setTableNames(#Nullable final String someList) {
if (StringUtils.isNotBlank(tableNames)) {
this.someList = Arrays.stream(StringUtils.split(someList, ","))
.map(String::trim)
.filter(StringUtils::isNotBlank)
.collect(Collectors.toList());
}
}
Hope it was helpful for using list-type parameters in spring-batch!
Thanks.

Serializing JsonArray as array and not object using Gson

I'm using Gson library but when it serializes the JsonArray object, it seems to serialize this as an object rather than a JSON array. i.e.
{ elements: [ {name:"value1}, {name:"value2"}]}
How do I remove the elements from being serialized?
I went to see the doctor, because my foot hurt when I walked on it. The doctor said, "Don't walk on it."
Generally, when working with an API like Gson, one would rather not even know that JsonArray exists, and they'd instead just use the data binding part of the API. So, instead of manually building a JsonArray, and then deal with serializing it, just feed a Java List or array to Gson.toJson(). For example:
List list = new ArrayList();
list.add("one");
list.add(2);
list.add(new Foo());
Gson gson = new Gson();
String json = gson.toJson(list);
System.out.println(json);
If that approach doesn't fit your needs and you're stuck using a JsonArray for some reason, then you might be tempted to just call its toString() method, since that does currently create what's ultimately desired, I wouldn't use it, because there is nothing in the documentation that says the toString() is guaranteed to create a valid JSON representation of the enclosed array contents. So, it might not return a String of the same format in future releases of Gson.
At any rate, if you really want to use a JsonArray, it should serialize well enough as follows.
JsonElement one = new JsonPrimitive("one");
JsonElement two = new JsonPrimitive(2);
JsonObject foo = new JsonObject();
foo.addProperty("foo", new Foo().foo);
JsonArray jsonArray = new JsonArray();
jsonArray.add(one);
jsonArray.add(two);
jsonArray.add(foo);
System.out.println(new Gson().toJson(jsonArray));
// ["one",2,{"foo":"hi"}]
Note: This answer is based on the Gson 2.2 API. I don't recall whether earlier versions of Gson included the overloaded toJson(JsonElement) methods.
If the toJson method is already being used in this fashion (to serialize a JsonArray), but the output is as demonstrated in the original question, recall that Java doesn't consider the runtime type when selecting amongst overloaded methods. It binds to the compile time type. (Lame -- I know.) So, you may need to cast the argument type to JsonElement, to let the compiler know which method to bind to. The following demonstrates what might be effectively happening in the original question.
System.out.println(new Gson().toJson((Object)jsonArray));
// {"elements":["one",2,{"foo":"hi"}]}

Two arrays or one in Map structure?

I'm trying to create a Map where the data will be static and not change after the program starts (actually loaded from a server)
Is it better to have two arrays, e.g. in Java:
String keys[] = new String[10];
String values[] = new String[10];
where keys[i] corresponds to values[i]?
or to keep them in a single array, e.g.
String[][] map[] = new String[10][2];
where map[i][0] is the key and map[i][1] is the value?
Personally, the first makes more sense to me, but the second makes more sense to my partner. Is either better performance-wise? Easier to understand?
Update: I'm looking to do this in JavaScript where Map and KeyValuePairs don't exist
Using a Map implementation (in Java) would make this easier to understand as the association is clearer:
static final Map<String, String> my_map;
static
{
my_map = new HashMap<String, String>();
// Populate.
}
A Hashtable looks like what you need. It hashes the keys in such a way that lookup can happen in O(1).
So, you're looking to do this in javascript. Any array or object in js in a map, so you could just do
var mymap = {'key1':'value1','key2':'value2'};

Resources