Tek-Tips is the largest IT community on the Internet today!

Members share and learn making Tek-Tips Forums the best source of peer-reviewed technical information on the Internet!

  • Congratulations gkittelson on being selected by the Tek-Tips community for having the most helpful posts in the forums last week. Way to Go!

Search/Filter in list with sub elements

Status
Not open for further replies.

fabien

Technical User
Sep 25, 2001
299
AU
Hi!

I have a list that contains sublists like:

seisinfo: {basic01 3dv 2 14.5684986115} {mig8b01 3dv 2 14.5684986115} {temp01 3dv 2 14.1837396622} {slice01 3dh 2 18.4079685211}

I would like to implement a Search/filter option:

Search: will search through all sublist items, if a match is found the sublist will appear first

Filter: Same as above but only the sublist that match are displayed

For instance if I Search for temp* then I would get
seisinfofiltered: {temp01 3dv 2 14.1837396622} {basic01 3dv 2 14.5684986115} {mig8b01 3dv 2 14.5684986115} {slice01 3dh 2 18.4079685211}

if I Filter for temp* I would get

seisinfofiltered: {temp01 3dv 2 14.1837396622}

What is the most efficient way to do this?
Thanks as always
 
I found the solution for the filter option with the function
proc filter {} {
global cur_seisinfo filter

set cur_seisinfo [lsearch -inline -all -glob $cur_seisinfo $filter]

}

NOw the problem is the Search function: I can apply the same test as above to create a new list say

set temp [lsearch -inline -all -glob $cur_seisinfo $filter]

now I need to merge temp and cur_seisinfo in deleting elements of temp from cur_seisinfo, how to do this?

 
Doesn't 'lsearch' return the list index for the found item? So in your example,

set temp [lsearch -inline -all -glob $cur_seisinfo $filter]

temp would be 4 or 15 or where ever the first match occurs.

If that is the case,

set match [lindex $cur_seisinfo $temp]
set everythingElse [lreplace $cur_seisinfo $temp $temp]
puts [concat $match $everythingElse]

lsearch will return -1 if there is no match. Only the first match will be returned.
 
Shooder, thanks but your statements don't work plus there can be several found items that need to go at the top..
 
Can you expand on 'don't work', what happens?

If there is more than 1 item that needs to be listed first then I would do the search manually but this may not be the most efficient method, i.e.,

set everythingElse

  • for {set c 0} {$c <= [llength $cur_seisinfo]} {incr c} {
    if [regexp $temp [lindex $cur_seisinfo $c]] {
    puts [lindex $cur_seisinfo $c]
    # or do what you want with it
    } else {
    lappend everythingElse [lindex $cur_seisinfo $c]
    }
    }
    puts $everythingElse

    You have to be careful with regexp though, especially when looking for numbers. Perhaps you could use your lsearch.....glob command but that gives an error on my machine - I'm on an old version of Tcl/TK though.
 
When I say don't work that means I get error messages when running it. Same with new code. Plus regexp won't work because temp is a list.

I found the solution of my problem with:

proc ldifference { list1 list2 } {
set difference


  • foreach element $list1 {
    set flag($element) {}
    }

    foreach element $list2 {
    if {![info exists flag($element)]} {
    lappend difference $element
    }
    }

    return $difference
    }

    #
    # Search for pattern in list and display the results at the top
    #
    proc Search {} {
    global cur_seisinfo filter

    #find match
    set match [lsearch -inline -all -glob $cur_seisinfo $filter]
    # find difference and add the match at the top
    set cur_seisinfo [concat $match [ldifference $match $cur_seisinfo]]


    }


    Thanks anyway!
 
Status
Not open for further replies.

Part and Inventory Search

Sponsor

Back
Top