🏠 back to Observable

Sorting and Searching in input tables

In the last cells of the attached notebook, I can combine the two searches (lyricist and composer) into a combined third search. For example, I choose Anand Bakshi as lyricist and A R Rahman as composer, and their individual outputs show under the lyricist and composer dropdowns, and the combo table shows up as the third table.
But for more readability, it will be great to have chosen a lyricist from dropdown, and then having in the ‘composer’ dropdown only those composers who have worked with the previously chosen lyricist.
For example, I can NOW choose Shailendra as lyricist, and then AR Rahman as composer, and then have the combo table as empty.
I want to choose Shailendra and then have no option in the composer table for A R Rahman (or any other composer who did not compose Shailendra’s lyrics).
Can I do that? I tried to do something with Inputs.bind, but cannot make it work.

Question#2: Is there a way of grabbing part of a string in a column for search? Like, can I choose the rows in a particular column (say, Singers,) where ‘Asha’ or ‘kar’ appear? Can I use Search to target a particular column instead of the whole table?

Also, how do I show the songs sung by Lata using color=unknown?

Thanks a lot in advance,
Rini

Here is the link to the notebook:
https://observablehq.com/@rbhttchr/hindifilmsongs_basic

1 Like

If I understand your question: When you select lyricist you want a drop down to contain just its composer's

viewof composer2 = Inputs.select(
  selectedlyricists.map((d) => d.Composer),
  { sort: true, unique: true, label: `Composers who work with ${lyricist}` },
)

Question 2: I use a bit of lodash

There might be better ways to write this.

_.compact(_.flattenDeep( selectedlyricists.map((d) => {
   let find = 'Rafi'
   let singer =  _.split(d.Singers, ',');  // lodash library  - split as there are more than one singer sometimes
     
   return (singer.map( s => {if (s === find) return d } ))
 })))

Question 2.2:
Do you mean like these?

I think the .scale should work with that as a string element.

2 Likes

Thank you, @rbhttchr and @hellonearthis ! I’ve also been looking into this.

Using @hellonearthis code example, I got a similar conditional selection working. Any suggestions for how to make the logic work for multiple selection?

1 Like

Thanks @hellonearthis ! The first code works like a charm. I am going to study the lodash code; thanks for using lodash: I have been thinking of delving into it and this will give me the prefect excuse.

1 Like

Thanks @aaronkyle for the great example! @hellonearthis, I have the same question as @aaronkyle. How about I want to pick the Singers who are under the category of lyricist/composer combination?

I used bind to link the three search boxes.

did = {
  let what = []
  let whom = _.trim(who) // https://lodash.com/docs/4.17.15#trim  (remove space)

  giitaayanW.map((d) => {
    let singer =  _.split(d.Singers, ',');  // lodash library  - split as there baybe more than artist
    singer.map( s => { if (_.trim(s) === whom) what.push(d) })

    let comp =  _.split(d.Composer, ',');  
    comp.map( c => { if (_.trim(c) === whom) what.push(d) })

    let lyric =  _.split(d.Lyricist, ',');  
    lyric.map( c => { if (_.trim(c) === whom) what.push(d) })
    
  })

 return _.uniq(what)  // removes double entries (mostly-ish)
}

Added _.trim to remove some leading spaces

2 Likes

Nice! This is really great!

I am still struggling a bit to return all the municipalities that match multiple districts in my example. I have found two StackOverflow discussions that seem to address this use case, but I cannot get them working:

and

Looks like it should be something like this:

filtered = municipalities_list.filter(function(element) {
   return municipalities_list.filter(function(selection) {
       return districts.indexOf(selection) > -1;
   }).length === districts.length;
});

or this

countriesFound2 = municipalities_list.filter(municipalities => 
    districts.indexOf(municipalities.key) != -1
);

… but I I haven’t quite cracked it. Any ideas?

Thanks so very much, @hellonearthis . This gives me the push to clean the dataset, finally.

Rini

1 Like

Maybe using a d3 group would help:

{
  let mu = d3.group(municipalities_list, d => d.Municipality)
  let what = []
  mu.forEach( (v,k,m) => {  // https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Map
  if (v.length > 1) what.push(k)
  })
return what
}```
1 Like

*Edit: Mike offered a solution!

Thanks @hellonearthis ! I am not sure I entirely follow that bit of code. I tried adapting in further so that what referred to my districts list, but still it didn’t entirely work.

I wonder if what I am after is not clear, or if I am asking something different than others. Essentially, I have a filter working for a single condition: you select 1 district, and you get a list of all municipalities in that district. But I can’t seem to get to so that if I select 2 or more districts, my list of municipalities grows to include those multiple selections:

1 Like

The scope of this question is different from the OP and might need to be in it’s own Talk question.

My d3.group just found all municipalities that where in more than one district.

1 Like