• Status: Solved
  • Priority: Medium
  • Security: Public
  • Views: 2303
  • Last Modified:

To remove duplicate values and return unique array

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
Mehram
Asked:
Mehram
  • 5
  • 3
  • 2
3 Solutions
 
lbushbyCommented:
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
 
MehramAuthor Commented:
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
 
MehramAuthor Commented:
My the term "imaginary" I mean dataobject->datastore to be created and destroyed at runtime
0
Hire Technology Freelancers with Gigs

Work with freelancers specializing in everything from database administration to programming, who have proven themselves as experts in their field. Hire the best, collaborate easily, pay securely, and get projects done right.

 
lbushbyCommented:
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
 
goodwinfamCommented:
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
 
MehramAuthor Commented:
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
 
MehramAuthor Commented:
Thanks a lot
0
 
goodwinfamCommented:
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
 
goodwinfamCommented:
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
 
MehramAuthor Commented:
Thanks again goodwinfam
0

Featured Post

Receive 1:1 tech help

Solve your biggest tech problems alongside global tech experts with 1:1 help.

  • 5
  • 3
  • 2
Tackle projects and never again get stuck behind a technical roadblock.
Join Now