[Last Call] Learn about multicloud storage options and how to improve your company's cloud strategy. Register Now

x
?
Solved

To remove duplicate values and return unique array

Posted on 2011-03-03
10
Medium Priority
?
2,225 Views
Last Modified: 2013-12-26
I am in search of a powerbuilder fuction which would accept an arry, remove duplicate values from array and return unique values of array

for example
is_dwm_data_colname[1] = 'sman_code'
is_dwm_data_colname[2] = 'area_code'
is_dwm_data_colname[3] = 'mfg_code'
is_dwm_data_colname[4] = 'area_code'
is_dwm_data_colname[5] = 'mfg_code'
is_dwm_data_colname[6] = 'sman_code'

the returned array should be
is_dwm_data_colname[1] = 'sman_code'
is_dwm_data_colname[2] = 'area_code'
is_dwm_data_colname[3] = 'mfg_code'


0
Comment
Question by:Mehram
[X]
Welcome to Experts Exchange

Add your voice to the tech community where 5M+ people just like you are talking about what matters.

  • Help others & share knowledge
  • Earn cash & points
  • Learn & ask questions
  • 5
  • 3
  • 2
10 Comments
 
LVL 2

Accepted Solution

by:
lbushby earned 1200 total points
ID: 35030125
There's no built in function but you could achieve what you want by copying the array to a column in a datastore then sort+filtering it to hide duplicate values before copying the column back to the array.  Example below:

// copy the array to a datastore (assumes datastore has been assigned a dataobject
// that contains a string column called 'dwm_data_colname')
lds_dedupe.Object.dwm_data_colname.primary = is_dwm_data_colname[]

// apply a sort+filter that discards duplicates
lds_dedupe.SetSort('dwm_data_colname A')
lds_dedupe.Sort()
lds_dedupe.Setfilter('GetRow()=1 OR dwm_data_colname <> dwm_data_colname[-1]')
lds_dedupe.Filter()

// copy the deduped column from the datastore back to the array
is_dwm_data_colname[] = lds_dedupe.Object.dwm_data_colname.primary

// the array now only contains distinct values
0
 

Author Comment

by:Mehram
ID: 35033721
Hi lbushby

I understand.

GetRow()=1 OR dwm_data_colname <> dwm_data_colname[-1] is a magical expression. My object Is achieved, but, please allow me to ask
Is it possible to create an imaginary datastore?
If so what is the syntax/script?

Thanks for your help.
0
 

Author Comment

by:Mehram
ID: 35034299
My the term "imaginary" I mean dataobject->datastore to be created and destroyed at runtime
0
Concerto Cloud for Software Providers & ISVs

Can Concerto Cloud Services help you focus on evolving your application offerings, while delivering the best cloud experience to your customers? From DevOps to revenue models and customer support, the answer is yes!

Learn how Concerto can help you.

 
LVL 2

Assisted Solution

by:lbushby
lbushby earned 1200 total points
ID: 35035069
Datastores objects are created and destroyed using CREATE/DESTROY.  Creating a dataobject at runtime can be done in several different ways.  Assuming you are actually connected to a database then probably the easiest way is to use SyntaxFromSQL to create a dataobject based on a SELECT statement.  The exact syntax will depend on the database in question.  The example below will work with Sybase SQLAnywhere which provides a 'dummy' table:

// EXAMPLE

datastore      lds_datastore
string      ls_syntax
string      ls_errors

// create a datastore
lds_datastore = create datastore

// generate syntax for a single string column called dwm_data_colname
// assumes SQLCA is connected to a database
ls_syntax = SQLCA.SyntaxFromSQL("SELECT '' AS dwm_data_colname FROM dummy", "", ls_errors )

// use the syntax to create a new dataobject
lds_datastore.Create(ls_syntax,ls_errors)

// the datastore is now ready to use as per the previous example

// having finished with the datastore, destroy it
destroy lds_datastore
 
0
 
LVL 1

Assisted Solution

by:goodwinfam
goodwinfam earned 800 total points
ID: 35035900
Here is what I have used for awhile extracted from my util nvo...   Note that this is from an export, so copy and paste accordingly (the first line before the ";" is the function and arg definition - not part of the script..

-------------------

public function integer of_arrayunique (long al_sourcevalues[], ref long al_uniquevalues[]);int            li_pos,li_cnt,li_tcnt,li_cnt2
long            ll_empty[],ll_value,ll_sourcevalues[]
boolean      lb_skip


// Initialize Return Array
ll_sourcevalues = al_sourcevalues
al_uniquevalues = ll_empty

// Loop Through Array Values
li_tcnt = upperbound(ll_sourcevalues)
for li_cnt = 1 to li_tcnt

      // Remove NULL Values
      lb_skip = FALSE
      ll_value = ll_sourcevalues[li_cnt]
      if isnull(ll_value) then continue

      // Compare
      for li_cnt2 = 1 to li_pos
            if ll_value = al_uniquevalues[li_cnt2] then
                  lb_skip = TRUE
                  continue
            end if
      next
      if lb_skip then continue

      // Include
      li_pos ++
      al_uniquevalues[li_pos] = ll_value

next

// Return
return(upperbound(al_uniquevalues))
end function

----------------------------------------------------------------

public function integer of_arrayunique (string as_sourcevalues[], ref string as_uniquevalues[], boolean ab_ignorecase);int            li_pos,li_cnt,li_tcnt,li_cnt2
string      ls_empty[],ls_value
boolean      lb_skip


// Initialize Return Array
as_uniquevalues = ls_empty

// Loop Through Array Values
li_tcnt = upperbound(as_sourcevalues)
for li_cnt = 1 to li_tcnt

      // Get Value
      lb_skip = FALSE
      ls_value = as_sourcevalues[li_cnt]
      if ab_ignorecase then
            ls_value = trim(lower(ls_value))
            if ls_value = "" then continue
      end if

      // Determine if Unique
      for li_cnt2 = 1 to li_pos
            if ls_value = lower(as_uniquevalues[li_cnt2]) then
                  lb_skip = TRUE
                  exit
            end if
      next
      if lb_skip then continue

      // Include
      li_pos ++
      as_uniquevalues[li_pos] = ls_value

next

// Return
return(upperbound(as_uniquevalues))
end function

Here are the other the functions that call the fully qualified function...

public function integer of_arrayunique (ref long al_return[])            ;return(of_arrayunique(al_return,al_return))
public function integer of_arrayunique (ref string as_return[])      ;return(of_arrayunique(as_return,as_return,FALSE))
public function integer of_arrayunique (ref string as_return[], boolean ab_ignorecase);return(of_arrayunique(as_return,as_return,ab_ignorecase))
0
 

Author Comment

by:Mehram
ID: 35036181
Great

The benefit of asking at EE is that you learn a lot of new things.
The of_arrayunique function has gone  easily into our user object uo_functions.

lbushby:
The creation of datastore at runtime was thrilling. I was in search of this since a long time.

U experts are lovely and Unselfish.

My best regards to both of U

(Mat)
0
 

Author Closing Comment

by:Mehram
ID: 35036287
Thanks a lot
0
 
LVL 1

Expert Comment

by:goodwinfam
ID: 35042058
Thanks,  
To appear less A.D.D. I  adjusted a few things...Please note that you may not wish to always skip NULL or empty values which is the assumption in these scripts.  The option whether or not to do so might also be a flag you pass (which I have in my actual code).  In the function handling strings you should add a line looking for a null value following "ls_value = as_sourcevalues[li_cnt]" like  (if isinull(ls_value) then ls_value = "" or if you are skipping empty values "if isinull(ls_value) then continue"...).  
0
 
LVL 1

Expert Comment

by:goodwinfam
ID: 35042188
Change "continue" to "exit" in the compare section for comparing long values above.

The final string value compare script...  
----------------
public function integer of_arrayunique (string as_sourcevalues[], ref string as_uniquevalues[], boolean ab_ignorecase, boolean ab_includeempty, boolean ab_untrimmed);int            li_cnt,li_tcnt,li_uniquecnt,li_totuniquecnt
string      ls_empty[],ls_value
boolean      lb_skip


// Initialize Return Array
as_uniquevalues = ls_empty

// Loop Through Array Values
li_tcnt = upperbound(as_sourcevalues)
for li_cnt = 1 to li_tcnt

      // Get Value
      lb_skip = FALSE
      ls_value = as_sourcevalues[li_cnt]
      if NOT(ab_untrimmed) then ls_value = trim(ls_value)
      if NOT(ab_includeempty) AND ( isnull(ls_value) or ls_value = "" ) then continue

      // Compare (this loop skipped first time through because li_totuniquecnt will = 0)
      for li_uniquecnt = 1 to li_totuniquecnt
            choose case TRUE
                  case ls_value = as_uniquevalues[li_uniquecnt]                                                                                                                                    ; lb_skip = TRUE      ; exit
                  case ab_ignorecase AND (lower(ls_value) = lower(as_uniquevalues[li_uniquecnt]))                                                                  ; lb_skip = TRUE      ; exit
                  case (ab_ignorecase AND ab_untrimmed) AND (lower(trim(ls_value)) = lower(trim(as_uniquevalues[li_uniquecnt])))      ; lb_skip = TRUE      ; exit
            end choose
      next
      if lb_skip then continue

      // Include
      li_totuniquecnt ++
      as_uniquevalues[li_totuniquecnt] = ls_value

next

// Return
return(upperbound(as_uniquevalues))
end function
0
 

Author Comment

by:Mehram
ID: 35144481
Thanks again goodwinfam
0

Featured Post

VIDEO: THE CONCERTO CLOUD FOR HEALTHCARE

Modern healthcare requires a modern cloud. View this brief video to understand how the Concerto Cloud for Healthcare can help your organization.

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

In our object-oriented world the class is a minimal unit, a brick for constructing our applications. It is an abstraction and we know well how to use it. In well-designed software we are not usually interested in knowing how objects look in memory. …
Update (December 2011): Since this article was published, the things have changed for good for Android native developers. The Sequoyah Project (http://www.eclipse.org/sequoyah/) automates most of the tasks discussed in this article. You can even fin…
THe viewer will learn how to use NetBeans IDE 8.0 for Windows to perform CRUD operations on a MySql database.
The viewer will learn how to use and create new code templates in NetBeans IDE 8.0 for Windows.
Suggested Courses

650 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question