@123213123 I saw that @Paulie78 provided a great solution already - and definitely what you should use. I just wanted to show an alternative way of achieving this using XML and XPath to extract out the data 🙂.
Note: If you had thousands of items in your original data then this might be a better approach as it avoids the need for an Apply to each so would be much quicker. Otherwise, I'd definitely recommend going with the original solution.
See full flow below. I'll go into each of the actions.

JSON is a Compose that contains your original data.

Select IDs is the same as what Paulie did where it extracts out a simple list of all the IDs. It uses the following expression.
item()?['ID']

XML is a Compose that converts your JSON data to XML so we can use XPath expressions to extract the data we want.
xml(json(concat('{"root": { value:', outputs('JSON'), '}}')))

The XML it creates is below.
<root>
<value>
<ID>87547</ID>
<FileName>test1.pdf</FileName>
<Title>task1</Title>
</value>
<value>
<ID>87547</ID>
<FileName>test2.pdf</FileName>
<Title>task1</Title>
</value>
<value>
<ID>87547</ID>
<FileName>test3.pdf</FileName>
<Title>task1</Title>
</value>
<value>
<ID>87549</ID>
<FileName>test877.xlsx</FileName>
<Title>task2</Title>
</value>
</root>
Select uses the following expressions to build up your final output.
//From (Unique IDs)
union(body('Select_IDs'), body('Select_IDs'))
//Map...
//ID
item()
//Filenames
xpath(xml(outputs('XML')), concat('//root/value[ID="', item(), '"]/FileName/text()'))
//Title
first(xpath(xml(outputs('XML')), concat('//root/value[ID="', item(), '"]/Title/text()')))

And the final output would be:
[
{
"ID": 87547,
"Filenames": [
"test1.pdf",
"test2.pdf",
"test3.pdf"
],
"Title": "task1"
},
{
"ID": 87549,
"Filenames": [
"test877.xlsx"
],
"Title": "task2"
}
]
