Need help for list manipulation


Please consider the below input text:


I have a list of these attributes of element Array in a variable statements of type TreeTypes.statement list

Hence, statements list contains below list:

Terminal (“Type”, “Cell”)
Terminal (“Dimension”, “8”)
Terminal (“Cell”, “BooleansAsBitfields”)
Terminal (“Cell”, “PassReuseOutputArgsAs”)
Terminal (“Cell”, “PassReuseOutputArgsThreshold”)
Terminal (“Cell”, “ZeroExternalMemoryAtStartup”)
Terminal (“PropName”, “DisabledProps”)

As you can see, there are duplicate attributes with name Cell
I want to merge the values of these Cell attributes in single Cell attribute.
In simple words, I want to have below statement list:

Terminal (“Type”, “Cell”)
Terminal (“Dimension”, “8”)
Terminal (“Cell”, “BooleansAsBitfields, PassReuseOutputArgsAs, PassReuseOutputArgsThreshold, ZeroExternalMemoryAtStartup”)
Terminal (“PropName”, “DisabledProps”)

I hope the problem is clear to you.
Could you please suggest a good list manipulation way to achieve this result?

Thank you in advance!

Use BatList.unique or unique_cmp or unique_hash
or even stdlib’s List.sort_uniq.

Hello UnixJunkie,
Thank you for this suggestion. But, I don’t want to remove any duplicate element. I want to merge the values of duplicate attribute.

I would create an empty map (using the standard library Map), then fold over the input list to add the list elements to the map using the update function. Note that you will need to be using at least OCaml version 4.06 for this function (or write your own).

The reason for using specifically the update function is that it gives you the chance to build the map value strings by appending each new duplicate string.

Then convert the map into the output list.

Thank you Amin :slight_smile:
Your solution is very much working for me.
Here is my code:

module StatementsMap = Map.Make(String)

			let map = StatementsMap.empty; in 								
			let build_map =
				List.fold_left (fun a s -> 
					match s with
					| Terminal (id, value) ->
						let b = StatementsMap.find_opt id a in
						if b <> None then begin
							let ct = (Terminal(id, concat_value (attribute_value b) value )) in
							StatementsMap.update id (fun _ -> Some ct) a
							StatementsMap.update id (fun _ -> Some s) a
					| Composite (_,_)  -> StatementsMap.update id (fun _ -> Some s) a
				) map statements; in

			let build_list =
			StatementsMap.fold(fun k d newlist -> d::newlist) build_map [] in

You saved my time. Thank you again.

1 Like