Home Php C# Sql C C++ Javascript Python Java Go Android Git Linux Asp.net Django .net Node.js Ios Xcode Cocoa Iphone Mysql Tomcat Mongodb Bash Objective-c Scala Visual-studio Apache Elasticsearch Jar Eclipse Jquery Ruby-on-rails Ruby Rubygems Android-studio Spring Lua Sqlite Emacs Ubuntu Perl Docker Swift Amazon-web-services Svn Html Ajax Xml Java-ee Maven Intellij-idea Rvm Macos Unix Css Ipad Postgresql Css3 Json Windows-server Vue.js Typescript Oracle Hibernate Internet-explorer Github Tensorflow Laravel Symfony Redis Html5 Google-app-engine Nginx Firefox Sqlalchemy Lucene Erlang Flask Vim Solr Webview Facebook Zend-framework Virtualenv Nosql Ide Twitter Safari Flutter Bundle Phonegap Centos Sphinx Actionscript Tornado Register | Login | Edit Tags | New Questions | 繁体 | 简体


10 questions online user: 39

0
votes
answers
18 views
+10

如何抓取JavaScript中的鍵值對 - Google Trends API

0

我正在使用google trends API最終將趨勢數據導出到excel文件。問題是我只想提取關鍵字的格式化時間和值。如何抓取JavaScript中的鍵值對 - Google Trends API

JS不是我的強項。我如何只拉這些參數?或者有沒有辦法將這些參數分配給鍵值字典對?

謝謝。

JSON輸出

{ 
    "default": { 
    "timelineData":[ 
     { 
     "time":"1511629200", 
     "formattedTime":"Nov 25, 2017 at 12:00 PM", 
     "formattedAxisTime":"Nov 25 at 12:00 PM", 
     "value":[44], 
     "formattedValue":["44"] 
     }, 
     { 
     "time":"1511632800", 
     "formattedTime":"Nov 25, 2017 at 1:00 PM", 
     "formattedAxisTime":"Nov 25 at 1:00 PM", 
     "value":[41], 
     "formattedValue":["41"] 
     } 
    ] 
    } 
} 

代碼

'use strict'; 

const googleTrends = require('google-trends-api'); 


var animals = ['hamsters', 'puppies']; 


for (var key in animals) { 

    console.log(animals[key]); 

    googleTrends.interestOverTime({ 
     keyword: key, 
     startTime: new Date(Date.now() - (167.9 * 60 * 60 * 1000)), 
     granularTimeResolution: true, 
    }, function(err, results) { 

     if (err) 
      console.log('oh no error!', err); 
     else 
      console.log(results); 
     console.log("--------------------------") 
    }); 
} 
+0

你的JSON對象還具有一個錯誤的額外'}' – Alan

沙发
0
0

這可能讓您開始提取你想要什麼:

theStuffIWant = []; 

for (each of output.default.timelineData) { 
    theStuffIWant.push({time: each.formattedTime, value: each.value[0]}); 
} 

console.log(theStuffIWant); 

// now you should have an array of the data you want. 

注意,值看起來像他們在具有一個值的數組,因此需要使用[0]索引。還要注意,變量output應該替換爲任何包含您的JSON數據的變量。

+0

獲取「類型錯誤:無法讀取未定義的屬性「默認」。 – Phum

板凳
0
1

提取所需的數據轉換成一個目的是遵循以功能性方式一鍵/值對圖案與存在檢查:

function extractTimeAndValue(data) { 
    var timelineData = (data && data.default && data.default.timelineData) || []; 

    return timelineData.reduce(function(timeAndValueObject, timeline) { 
    var time = timeline.formattedTime; 
    var value = timeline.value; 

    return Object.assign(
    {}, 
    timeAndValueObject, 
    time && value ? {[time]: value} : {} 
    ); 
    }, {}); 
} 
0
votes
answers
12 views
+10

當被稱爲右值析構函數/這是正確的

3

爲以下包裝類跟上std::unique_ptr中間對象來訪問me成員而不復制me的「OK」的方式?當被稱爲右值析構函數/這是正確的

下面是示例

#include <iostream> 
#include <memory> 

/* myobj from another library */ 
class myobj { 
public: 
    std::string me; /* actual member of interest is larger and more 
         complicated. Don't want to copy of me or myobj */ 

    /* more members in actual class */ 

    myobj(std::string i_am) { 
     /* more stuff happens in constructor */ 
     me = i_am; 
    } 

    ~myobj(){ 
     std::cout << me << ": Goodbye" << std::endl; 
    } 
}; 

/* A function in another library */ 
void who_is_this(std::string *who){ 
    std::cout << "This is " << *who << std::endl; 
} 

/* wrapper which I define */ 
class myobj_wrapper { 
    using obj_ptr = std::unique_ptr<myobj>; 
    obj_ptr ptr; 

public: 
    std::string *who; 

    myobj_wrapper(std::string i_am): 
     ptr(new myobj(i_am)), who(&ptr.get()->me) {} 

    myobj_wrapper(myobj &the_obj): who(&the_obj.me) { } 
}; 

int main() 
{ 
    { 
     myobj bob("Bob"); 
     who_is_this(myobj_wrapper(bob).who); 
    } 

    who_is_this(myobj_wrapper("Alice").who); 

    return 0; 
} 

所得程序收率

This is Bob 
Bob: Goodbye 
This is Alice 
Alice: Goodbye 

我定義myobj_wrapper多個對象以獲得who指針。在who_is_this函數中評估之前,我不確定感興趣的對象(上面的std::string)是否會被銷燬。 它似乎不是從上面,但我應該期待這一點?上述解決方案是否存在缺陷?

+0

代碼雖然我必須承認我不太明白這個練習的重點,但我不明白這個問題應該是一個解決方案在...上。 –

+0

** rvalue destructor **是什麼意思? –

+0

我的意思是'who_is_this(myobj_wrapper(「Alice」)。who);' –

沙发
0
1

我不知道,但這裏是我的觀點:

who_is_this(myobj_wrapper("Alice").who); 

這將創建一個包裝對象,將採取字符串文字作爲參數。然後,一個myobj實例將被動態創建,並移交給一個唯一的指針。通過這個實例,我們得到它的數據(字符串),並從包裝類指向它的傳統指針。所以,現在who指向me,即愛麗絲。

我們通過who(這是一個指針):

void who_is_this(std::string *who) 

這意味着該函數的參數who副本,而是指向原始數據。

所以現在整個問題是當包裝器對象超出範圍時(因此它的數據成員(唯一指針)也將超出範圍,這意味着已動態創建的myobj實例將被垃圾收集,這又意味着me將走出去的範圍太,等會who

包裝對象將走出去的範圍,後who_is_this()得到執行,這意味着你的代碼是OK。

+0

「的動態分配對象_包含對象將在** who_is_this()被執行後超出範圍**,這意味着您的代碼OK_「很酷,謝謝你的回答! –

+1

Thx。我想有人可能會添加關於陷阱的評論。我猜沒有任何。具體的例子是[這裏](https://github.com/boennecd/dynamichazard/blob/master/src/problem_data.h),我使用Armadillo庫。請參閱'map_res'類,例如'lp_map'方法。有時需要新的'arma :: vec',而在其他時候則不需要創建新的對象。 (忽視類之上的評論 - 這是錯誤的)。 –

0
votes
answers
24 views
+10

使用具有附加條件的全文搜索來搜索1300萬條記錄

1

使用其他條件執行SQL Server全文搜索時出現性能問題。 (SQL Server 2012)使用具有附加條件的全文搜索來搜索1300萬條記錄

我想根據搜索過濾器列表(表值參數)過??濾數據,它將返回匹配過濾器的所有記錄,並且過濾器的單個記錄沒有表中的任何記錄。

對於列SNAME,全文搜索索引已經在表Names上。

在存儲過程中,表類型參數SearchFilter用於傳遞名稱和地址信息列表。

這兩個表都有超過1400萬條記錄,當我們在過濾器列表中傳遞1000個唯一記錄並執行該過程時,大約需要7分鐘才能返回結果(1400條記錄)。

過濾標準是:包含(名稱)和streetaddress,城市,州,郵編完全匹配。

是否有任何替代避免while循環爲SQL Server CONTAINS函數所需的字符串值或變量?

CREATE TABLE [dbo].[Names] 
(
    [ID] [int] IDENTITY(1,1) NOT NULL, 
    [UIN] [varchar](9) NULL, 
    [SNAME] [varchar](500) NULL, 
    CONSTRAINT [PK_Names] 
     PRIMARY KEY CLUSTERED ([ID] ASC) 
) 

CREATE TABLE [dbo].[ADDRESSES] 
(
    [UIN] [varchar](9) NULL, 
    [STREET1] [varchar](100) NULL, 
    [STREET2] [varchar](50) NULL, 
    [CITY] [varchar](30) NULL, 
    [STATE] [varchar](2) NULL, 
    [ZIP] [varchar](10) NULL  
) ON [PRIMARY] 

CREATE TYPE [dbo].[SearchFilter] AS TABLE 
(
    [UIN] [varchar](40) NULL, 
    [SNAME] [varchar](max) NULL, 
    [StreetAddress] [varchar](max) NULL, 
    [City] [varchar](max) NULL, 
    [State] [varchar](50) NULL, 
    [Zip] [varchar](20) NULL 
) 

-- Stored procedure logic 
DECLARE @filterList AS [dbo].[SearchFilter] 

DECLARE @NoOfRows INT, @counter INT = 0 

SET @NoOfRows = (SELECT COUNT(1) FROM @filterList) 

DECLARE @result TABLE (UIN varchar(40), 
         NAME varchar(500), 
         StreetAddress varchar(1000), 
         Zipcode varchar(20), 
         State varchar(20), 
         City varchar(1000), 
         IsRecordFound varchar(50) 
        ); 

WHILE (@NoOfRows > @counter) 
BEGIN 
    DECLARE @SearchName VARCHAR(4000) 

    SET @SearchName = (SELECT '"'+SNAME+'"' FROM @filterList ORDER BY SNAME OFFSET @counter ROWS FETCH NEXT 1 ROWS ONLY) 

    --Start: Process to Select Records 
    ;WITH Filter_CTE AS 
    (
     SELECT 
      SNAME, StreetAddress, City, State, ZipCode 
     FROM 
      @filterList 
     ORDER BY 
      SNAME 
      OFFSET @counter ROWS FETCH NEXT 1 ROWS ONLY 
    ) 
    INSERT INTO @result (UIN, NAME, STREETADDRESS, CITY, STATE, ZIPCODE, PHONE, IsRecordFound) 
     SELECT DISTINCT 
      en.UIN, ISNULL(en.SNAME, Filter_CTE.SNAME), 
      Filter_CTE.StreetAddress, Filter_CTE.ZipCode, 
      Filter_CTE.state, Filter_CTE.City, 
      IIF(en.UIN IS NULL, 'Not Found', 'Found') AS IsRecordFound 
     FROM 
      dbo.Names en 
     INNER JOIN 
      dbo.ADDRESSES ea ON en.UIN = ea.UIN 
     RIGHT JOIN 
      Filter_CTE ON ea.ZIP = Filter_CTE.Zip 
         AND ea.STATE = Filter_CTE.State 
         AND ea.CITY = Filter_CTE.City 
         AND (ISNULL(ea.STREET1, '') + ' ' + ISNULL(ea.STREET2, '')) = Filter_CTE.StreetAddress 
         AND CONTAINS(en.SNAME,@SearchName) 
      --END 

    SET @counter += 1 
END 

SELECT 
    UIN, NAME, STREETADDRESS, CITY, STATE, ZIPCODE, PHONE 
FROM 
    @result 
+1

你可以嘗試'喜歡 '%%''的比賽,而不是'包含()' - 這_might_更快depoending由SQLSERVER做了優化。查詢優化高度依賴於使用的數據和計劃cerated/indexes y - 如果您真的必須搜索那麼多的數據,它將需要一些時間。 –

+0

你確定表名字和地址是否覆蓋了你的'RIGHT JOIN Filter_CTE'子句中使用的所有列的索引? – andrews

+0

是的,表名稱和地址具有覆蓋您的RIGHT JOIN Filter_CTE子句 –

沙发
0
0

目前,它是不可能在CONTAINSCONTAINSTABLE使用列名作爲搜索條件。因此,在應用了FTS謂詞的數據表和SearchFilter表之間不能執行直接JOIN

當前在其他問題/論壇中找到的解決方案是循環訪問過濾器列表並在搜索條件的變量中輸入CONTAINS,就像您一樣。所以,你不會擺脫這個循環。

然而,看着你的查詢我看到了一些可能會影響性能的其他問題:在INSERT INTO @result ... SELECT DISTINCT ...

  1. DISTINCT條款。它是在你的JOIN到有數百萬記錄的表的級別。雖然我明白,最後的結果可能只包含幾千行,最好是移動DISTINCT這一行:

    SELECT DISTINCT 
        UIN, NAME, STREETADDRESS, CITY, STATE, ZIPCODE, PHONE 
    FROM 
        @result 
    
  2. 這種情況AND (ISNULL(ea.STREET1, '') + ' ' + ISNULL(ea.STREET2, '')) = Filter_CTE.StreetAddress肯定不是優化搜索。您使用連接和函數(ISNULL()),它可以防止SQL Server通過dbo.ADDRESSES ea表使用現有索引。檢查這個問題:What makes a SQL statement sargable?看看如何構建JOIN/WHERE條件,以便允許使用索引。 在這種特定的情況下最好是一計算列添加到dbo.Addresses表,然後生成在其上的索引(或將其添加到現有的索引):

    CREATE TABLE [dbo].[ADDRESSES] 
    (
        ... 
        STREET as (ISNULL(ea.STREET1, '') + ' ' + ISNULL(ea.STREET2, '')), 
        ... 
    ) 
    

所以固定上述1然後在RIGHT JOIN中註釋AND CONTAINS(en.SNAME,@SearchName)條件並注意執行時間。之後,取消註釋CONTAINS的條件並查看添加了多少延遲。通過這種方式,您肯定會知道FTS引擎是否因延遲而受到責備,或者您的主查詢本身需要改進。

爲了能夠提供更多建議,我們需要查看您的過程的執行計劃。您可以使用此頁面共享您的查詢執行計劃:https://www.brentozar.com/pastetheplan/

HTH

+0

感謝您花費在我的問題上的寶貴時間和努力。 我已經更新了while循環中的邏輯,並且還實現了您的計算列索引的建議之一,並且它改進了存儲過程的整體性能。 –

+0

@ K.Engineer太棒了!我很高興能夠提供幫助。我希望你至少有15個代表能夠投我的答案,呵呵:)。 – andrews

0
votes
answers
24 views
+10

的Python:嘗試,除了ValueError異常只能使用一次

0

我有一個分配做出華氏Clesius計算器和使用嘗試,除了ValueError功能,但我不能輸入錯誤的值超過一次或崩潰。我希望用戶輸入一個數字而不是字母。這是我的代碼現在的樣子的Python:嘗試,除了ValueError異常只能使用一次

print("Hej och välkommen till Fahrenheit omvandlaren") 
Fahrenheit = (input("Vänligen ange grader i Fahrenheit: ")) 

try: 
    test = float(Fahrenheit) 

except ValueError: 
    Fahrenheit = (input("Vänligen ange ett tal!")) 

Celsius = (float(Fahrenheit)-32)*5/9 
print(Fahrenheit, "Fahernheit är lika med",(round(Celsius,2)),"grader Celsius") 

我在通用新的節目,並希望如果你能以簡單的方式解釋如何使人們有可能多次輸入的字符串,而無需在程序崩潰

+0

儘量避免把代碼中的'except'塊,能夠產生異常。 –

沙发
0
1

你可以可以把輸入在一個循環:

while True: 
    fahrenheit = (input("Vänligen ange grader i Fahrenheit: ")) 
    try: 
     test = float(fahrenheit) 
     break 
    except ValueError: 
     pass 
板凳
0
0

你除了條款要求從用戶的輸入。但第二個輸入未經測試。 因此,當第二個輸入用於float函數時,如果輸入不正確,它將失敗。

如果你希望用戶繼續給輸入,直到他輸入一個數字,你需要一個循環。 在該循環中,您需要一個try-except子句(或其他一些測試)來測試輸入是否是數字。

0
votes
answers
28 views
+10

角4動態表單 - 如果未觸及空值 - 如何獲得這些顯示的默認值?

1

使用Angular 4.x我創建了動態表單。 (它允許根據情況添加或刪除字段。) 一開始就一切都很好。所有值(開始,結束,類別)都有一個在模板中設置的初始值。在視覺上,一切看起來都很完美如果根據頁面上的其他對象或與頁面上的其他對象同步正確猜測值,則用戶無需更改任何內容。角4動態表單 - 如果未觸及空值 - 如何獲得這些顯示的默認值?

問題:如果用戶沒有更改這些值,它們將從窗體返回爲「」。儘管在頁面上展示了不錯的內容。 已經玩過很多原始/骯髒和感動的旗幟。沒有改變。

最後,我找到了開始和結束值的解決方法。不是很漂亮。只需在typescript中進行相同的日期轉換,並將formbuilder中的開始和結束值設置爲完全相同的東西。以爲我可以從模板中刪除value =來減少重複的代碼。但是,如果我這樣做,輸入字段在頁面上保持空白。

但是,此解決方法無法用於category_id事件,該事件可以在頁面上實時更改。更好的是,categoriesService.selectedCategory可以是none。我們會對categoriesService.selectedCategory.id字段感興趣。

頁面上的視覺事物完成,看起來不錯。但是如何在提交時從頁面獲取這些值? (即使用戶沒有與價值觀玩)

這是我的模板看起來像:

<form [formGroup]="myNewCustForm" novalidate (ngSubmit)="save(myNewCustForm)"> 
... 
<label>product</label> 
<select class="form-control" formControlName="category_id"> 
    <option 
    *ngFor="let category of categoriesService.categories" 
    [ngValue]="category.id" 
    [selected]="categoriesService.selectedCategory ? category.id === categoriesService.selectedCategory.id : false"> 
     {{category.name}} 
    </option> 
</select> 
... 
<label>start</label> 
<div class="input-group"> 
    <input 
    class="form-control" 
    placeholder="yyyy-mm-dd" 
    name="dprestart" 
    ngbDatepicker 
    #dpstart="ngbDatepicker" 
    value="{{startDate | date: 'yyyy-MM-dd'}}" 
    formControlName="start"/> 
    <button 
    class="input-group-addon" 
    (click)="dpstart.toggle()" 
    type="button"> 
    <i class="fa fa-calendar" aria-hidden="true"></i> 
    </button> 
</div> 

打字稿(角4.x版):

return this.formBuilder.group({ 
    start: this.startDateString, 
    end: this.endDateString, 
    category_id: '' 
}); 

而在保存方法:有關的startDate和結束日期

this.presences.value.forEach(presence => { 
    ... 
    console.log(presence.start); 
    console.log(presence.category_id); 
    ... 
} 

更多信息:

// presence default values - declarations 
startDate: Date; 
startDateString: string; 
endDate: Date; 
endDateString: string; 

,然後在呼籲ngInit方法:

this.endDate = new Date(Date.now()); 
this.endDate.setHours(0, 0, 0); 
if(this.endDate.getDay() > 4) { 
    this.endDate.setDate(this.endDate.getDate()+13-(this.endDate.getDay() || 7)); 
} else { 
    this.endDate.setDate(this.endDate.getDate()+6-(this.endDate.getDay() || 7)); 
} 
this.startDate = new Date(Date.now()); 
this.startDateString = this.datePipe.transform(this.startDate, 'yyyy-MM-dd'); 
this.endDateString = this.datePipe.transform(this.endDate, 'yyyy-MM-dd'); 
+0

剛剛發現了另一個解決方法。現在只要檢查結果是否返回「」。如果是這樣,我會嘗試重新計算默認值可能是什麼。有沒有乾淨的方式? – user3387542

+0

此替代方法也不起作用。 – user3387542

+0

這是否有一個笨蛋? –

沙发
0
1

與活性形式,像valuedisabledselected不起作用。你需要做的是利用表單控件,並做他們想做的事情。此外,與ngbDatepicker,它想要的價值,應該是NgbDateStruct類型,看起來像:

{ 
    "year": 2017, 
    "month": 11, 
    "day": 22 
} 
與日期選取器

所以,你需要的日期格式,以便日期選擇接受它,這裏有一個如何一個簡單的示例它應該看起來像:

startDateString: NgbDateStruct = {year: new Date().getFullYear(), 
            month: new Date().getMonth() + 1, 
            day: new Date().getDate()}; 

然後,您將分配給表單控件,就像你有。

對於select,如上所述,Angular完全不關心selected。什麼,你需要做的是與你的服務越來越每當它改變了值使用patchValue(或setValue):

this.myNewCustForm.controls.category_id.setValue('some value') 

看來你是使用服務此值。然後可以使用settergetter來達到此目的將值設置爲表單控件。

68
votes
answers
11 views
+10

How do I make the method return type generic?

Consider this example (typical in OOP books):

I have an Animal class, where each Animal can have many friends.
And subclasses like Dog, Duck, Mouse etc which add specific behavior like bark(), quack() etc.

Here's the Animal class:

public class Animal {
    private Map<String,Animal> friends = new HashMap<>();

    public void addFriend(String name, Animal animal){
        friends.put(name,animal);
    }

    public Animal callFriend(String name){
        return friends.get(name);
    }
}

And here's some code snippet with lots of typecasting:

Mouse jerry = new Mouse();
jerry.addFriend("spike", new Dog());
jerry.addFriend("quacker", new Duck());

((Dog) jerry.callFriend("spike")).bark();
((Duck) jerry.callFriend("quacker")).quack();

Is there any way I can use generics for the return type to get rid of the typecasting, so that I can say

jerry.callFriend("spike").bark();
jerry.callFriend("quacker").quack();

Here's some initial code with return type conveyed to the method as a parameter that's never used.

public<T extends Animal> T callFriend(String name, T unusedTypeObj){
    return (T)friends.get(name);        
}

Is there a way to figure out the return type at runtime without the extra parameter using instanceof? Or at least by passing a class of the type instead of a dummy instance.
I understand generics are for compile time type-checking, but is there a workaround for this?

沙发
+140

Additionally you can ask the method to return the value in a given type this way

<T> T methodName(Class<T> var);

More examples here at Oracle Java documentation

板凳
+120

Here is the simpler version:

public <T> T callFriend(String name) {
    return (T) friends.get(name); //Casting to T not needed in this case but its a good practice to do
}

Fully working code:

    public class Test {
        public static class Animal {
            private Map<String,Animal> friends = new HashMap<>();

            public void addFriend(String name, Animal animal){
                friends.put(name,animal);
            }

            public <T> T callFriend(String name){
                return (T) friends.get(name);
            }
        }

        public static class Dog extends Animal {

            public void bark() {
                System.out.println("i am dog");
            }
        }

        public static class Duck extends Animal {

            public void quack() {
                System.out.println("i am duck");
            }
        }

        public static void main(String [] args) {
            Animal animals = new Animal();
            animals.addFriend("dog", new Dog());
            animals.addFriend("duck", new Duck());

            Dog dog = animals.callFriend("dog");
            dog.bark();

            Duck duck = animals.callFriend("duck");
            duck.quack();

        }
    }

這是最好的答案。 - Marco Altieri 3月10日22:06

地板
+100

As you said passing a class would be OK, you could write this:

public <T extends Animal> T callFriend(String name, Class<T> clazz) {
   return (T) friends.get(name);
}

And then use it like this:

jerry.callFriend("spike", Dog.class).bark();
jerry.callFriend("quacker", Duck.class).quack();

Not perfect, but this is pretty much as far as you get with Java generics. There is a way to implement Typesafe Heterogenous Containers (THC) using Super Type Tokens, but that has its own problems again.

我很抱歉,這就是laz所說的完全相同的答案,所以你要么是在復制他,要么是在復制你。 - 詹姆斯麥克馬洪09年1月16日16:06

這是一種傳遞Type的巧妙方法。但仍然像施密特所說的那樣安全。我仍然可以通過一個不同的類,類型轉換將炸彈。mmyers第2回復設置返回類型似乎更好 - Sathish 09年1月16日在16:10

Nemo,如果你查看發佈時間,你會看到我們在同一時刻發布了它們。而且,它們並不完全相同,只有兩條線。 - Fabian Steeg於2009年1月16日16:17

@Fabian我發布了類似的答案,但Bloch的幻燈片和Effective Java上發布的內容之間存在重要差異。他使用了Class 而不是TypeRef。但這仍然是一個很好的答案。 - Craig P. Motlin 09年1月16日17:10

4楼
+70

Based on the same idea as Super Type Tokens, you could create a typed id to use instead of a string:

public abstract class TypedID<T extends Animal> {
  public final Type type;
  public final String id;

  protected TypedID(String id) {
    this.id = id;
    Type superclass = getClass().getGenericSuperclass();
    if (superclass instanceof Class) {
      throw new RuntimeException("Missing type parameter.");
    }
    this.type = ((ParameterizedType) superclass).getActualTypeArguments()[0];
  }
}

But I think this may defeat the purpose, since you now need to create new id objects for each string and hold on to them (or reconstruct them with the correct type information).

Mouse jerry = new Mouse();
TypedID<Dog> spike = new TypedID<Dog>("spike") {};
TypedID<Duck> quacker = new TypedID<Duck>("quacker") {};

jerry.addFriend(spike, new Dog());
jerry.addFriend(quacker, new Duck());

But you can now use the class in the way you originally wanted, without the casts.

jerry.callFriend(spike).bark();
jerry.callFriend(quacker).quack();

This is just hiding the type parameter inside the id, although it does mean you can retrieve the type from the identifier later if you wish.

You'd need to implement the comparison and hashing methods of TypedID too if you want to be able to compare two identical instances of an id.

5楼
+60

"Is there a way to figure out the return type at runtime without the extra parameter using instanceof?"

As an alternative solution you could utilise the Visitor pattern like this. Make Animal abstract and make it implement Visitable:

abstract public class Animal implements Visitable {
  private Map<String,Animal> friends = new HashMap<String,Animal>();

  public void addFriend(String name, Animal animal){
      friends.put(name,animal);
  }

  public Animal callFriend(String name){
      return friends.get(name);
  }
}

Visitable just means that an Animal implementation is willing to accept a visitor:

public interface Visitable {
    void accept(Visitor v);
}

And a visitor implementation is able to visit all the subclasses of an animal:

public interface Visitor {
    void visit(Dog d);
    void visit(Duck d);
    void visit(Mouse m);
}

So for example a Dog implementation would then look like this:

public class Dog extends Animal {
    public void bark() {}

    @Override
    public void accept(Visitor v) { v.visit(this); }
}

The trick here is that as the Dog knows what type it is it can trigger the relevant overloaded visit method of the visitor v by passing "this" as a parameter. Other subclasses would implement accept() exactly the same way.

The class that wants to call subclass specific methods must then implement the Visitor interface like this:

public class Example implements Visitor {

    public void main() {
        Mouse jerry = new Mouse();
        jerry.addFriend("spike", new Dog());
        jerry.addFriend("quacker", new Duck());

        // Used to be: ((Dog) jerry.callFriend("spike")).bark();
        jerry.callFriend("spike").accept(this);

        // Used to be: ((Duck) jerry.callFriend("quacker")).quack();
        jerry.callFriend("quacker").accept(this);
    }

    // This would fire on callFriend("spike").accept(this)
    @Override
    public void visit(Dog d) { d.bark(); }

    // This would fire on callFriend("quacker").accept(this)
    @Override
    public void visit(Duck d) { d.quack(); }

    @Override
    public void visit(Mouse m) { m.squeak(); }
}

I know it's a lot more interfaces and methods than you bargained for, but it's a standard way to get a handle on every specific subtype with precisely zero instanceof checks and zero type casts. And it's all done in a standard language agnostic fashion so it's not just for Java but any OO language should work the same.

6楼
+50

Not possible. How is the Map supposed to know which subclass of Animal it's going to get, given only a String key?

The only way this would be possible is if each Animal accepted only one type of friend (then it could be a parameter of the Animal class), or of the callFriend() method got a type parameter. But it really looks like you're missing the point of inheritance: it's that you can only treat subclasses uniformly when using exclusively the superclass methods.

7楼
+50

I've written an article which contains a proof of concept, support classes and a test class which demonstrates how Super Type Tokens can be retrieved by your classes at runtime. In a nutshell, it allows you to delegate to alternative implementations depending on actual generic parameters passed by the caller. Example:

  • TimeSeries<Double> delegates to a private inner class which uses double[]
  • TimeSeries<OHLC> delegates to a private inner class which uses ArrayList<OHLC>

See: Using TypeTokens to retrieve generic parameters

Thanks

Richard Gomes - Blog

非常好的文章! - Fabian Knapp 2013年2月10日11:25

的確,感謝您分享您的見解,您的文章真的解釋了一切! - Yann-GaëlGuéhéneuc2013年4月12日9:20

8楼
+20

Not really, because as you say, the compiler only knows that callFriend() is returning an Animal, not a Dog or Duck.

Can you not add an abstract makeNoise() method to Animal that would be implemented as a bark or quack by its subclasses?

如果動物有多種方法甚至不屬於可以抽象的共同行動呢?我需要這個用於具有不同動作的子類之間的通信,其中我可以傳遞Type,而不是實例。 - 赤腳於2009年1月16日16:01

你真的只是回答了你自己的問題 - 如果動物有獨特的動作,那麼你必須投射到那個特定的動物。如果動物具有可與其他動物分組的動作,則可以在基類中定義抽像或虛擬方法並使用它。 - 馬特喬丹於2009年1月16日16:15

9楼
+20

What you're looking for here is abstraction. Code against interfaces more and you should have to do less casting.

The example below is in C# but the concept remains the same.

using System;
using System.Collections.Generic;
using System.Reflection;

namespace GenericsTest
{
class MainClass
{
    public static void Main (string[] args)
    {
        _HasFriends jerry = new Mouse();
        jerry.AddFriend("spike", new Dog());
        jerry.AddFriend("quacker", new Duck());

        jerry.CallFriend<_Animal>("spike").Speak();
        jerry.CallFriend<_Animal>("quacker").Speak();
    }
}

interface _HasFriends
{
    void AddFriend(string name, _Animal animal);

    T CallFriend<T>(string name) where T : _Animal;
}

interface _Animal
{
    void Speak();
}

abstract class AnimalBase : _Animal, _HasFriends
{
    private Dictionary<string, _Animal> friends = new Dictionary<string, _Animal>();


    public abstract void Speak();

    public void AddFriend(string name, _Animal animal)
    {
        friends.Add(name, animal);
    }   

    public T CallFriend<T>(string name) where T : _Animal
    {
        return (T) friends[name];
    }
}

class Mouse : AnimalBase
{
    public override void Speak() { Squeek(); }

    private void Squeek()
    {
        Console.WriteLine ("Squeek! Squeek!");
    }
}

class Dog : AnimalBase
{
    public override void Speak() { Bark(); }

    private void Bark()
    {
        Console.WriteLine ("Woof!");
    }
}

class Duck : AnimalBase
{
    public override void Speak() { Quack(); }

    private void Quack()
    {
        Console.WriteLine ("Quack! Quack!");
    }
}
}

這個問題與編碼而不是概念有關。 - user1043000 2015年2月6日4:55

@nitro你是對的。我提供了我能提供的幫助。 - Nestor Ledon 2015年2月6日19:35

10楼
+20

There are a lot of great answers here, but this is the approach I took for an Appium test where acting on a single element can result in going to different application states based on the user's settings. While it doesn't follow the conventions of OP's example, I hope it helps someone.

public <T extends MobilePage> T tapSignInButton(Class<T> type) throws NoSuchMethodException, IllegalAccessException, InvocationTargetException, InstantiationException {
    //signInButton.click();
    return type.getConstructor(AppiumDriver.class).newInstance(appiumDriver);
}
  • MobilePage is the super class that the type extends meaning you can use any of its children (duh)
  • type.getConstructor(Param.class, etc) allows you to interact with the constructor of the type. This constructor should be the same between all expected classes.
  • newInstance takes a declared variable that you want to pass to the new objects constructor

If you don't want to throw the errors you can catch them like so:

public <T extends MobilePage> T tapSignInButton(Class<T> type) {
    // signInButton.click();
    T returnValue = null;
    try {
       returnValue = type.getConstructor(AppiumDriver.class).newInstance(appiumDriver);
    } catch (Exception e) {
        e.printStackTrace();
    }
    return returnValue;
}

據我了解,這是使用泛型的最佳和最優雅的方式。 - cbaldan 2017年11月30日13:19

11楼
+10

I know this is a completely different thing that the one asked. Another way of resolving this would be reflection. I mean, this does not take the benefit from Generics, but it lets you emulate, in some way, the behavior you want to perform (make a dog bark, make a duck quack, etc.) without taking care of type casting:

import java.lang.reflect.InvocationTargetException;
import java.util.HashMap;
import java.util.Map;

abstract class AnimalExample {
    private Map<String,Class<?>> friends = new HashMap<String,Class<?>>();
    private Map<String,Object> theFriends = new HashMap<String,Object>();

    public void addFriend(String name, Object friend){
        friends.put(name,friend.getClass());
        theFriends.put(name, friend);
    }

    public void makeMyFriendSpeak(String name){
        try {
            friends.get(name).getMethod("speak").invoke(theFriends.get(name));
        } catch (IllegalArgumentException e) {
            e.printStackTrace();
        } catch (SecurityException e) {
            e.printStackTrace();
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        } catch (InvocationTargetException e) {
            e.printStackTrace();
        } catch (NoSuchMethodException e) {
            e.printStackTrace();
        }
    } 

    public abstract void speak ();
};

class Dog extends Animal {
    public void speak () {
        System.out.println("woof!");
    }
}

class Duck extends Animal {
    public void speak () {
        System.out.println("quack!");
    }
}

class Cat extends Animal {
    public void speak () {
        System.out.println("miauu!");
    }
}

public class AnimalExample {

    public static void main (String [] args) {

        Cat felix = new Cat ();
        felix.addFriend("Spike", new Dog());
        felix.addFriend("Donald", new Duck());
        felix.makeMyFriendSpeak("Spike");
        felix.makeMyFriendSpeak("Donald");

    }

}
12楼
+10

what about

public class Animal {
private Map<String,<T extends Animal>> friends = new HashMap<String,<T extends Animal>>();

public <T extends Animal> void addFriend(String name, T animal){
    friends.put(name,animal);
}

public <T extends Animal> T callFriend(String name){
    return friends.get(name);
}

}

13楼
+10

I did the following in my lib kontraktor:

public class Actor<SELF extends Actor> {
    public SELF self() { return (SELF)_self; }
}

subclassing:

public class MyHttpAppSession extends Actor<MyHttpAppSession> {
   ...
}

at least this works inside the current class and when having a strong typed reference. Multiple inheritance works, but gets really tricky then :)

14楼
0

There is another approach, you can narrow the return type when you override a method. In each subclass you would have to override callFriend to return that subclass. The cost would be the multiple declarations of callFriend, but you could isolate the common parts to a method called internally. This seems a lot simpler to me than the solutions mentioned above, and does not need an extra argument to determine the return type.

我不確定你的意思是“縮小返回類型”。Afaik,Java和大多數類型的語言不會基於返回類型重載方法或函數。例如,從編譯器的角度來看,public int getValue(String name){}與public boolean getValue(String name){}無法區分。您需要更改參數類型或添加/刪除要識別的重載參數。也許我只是誤解了你... - The One True Colter 18年8月6日凌晨2點09分

在java中,您可以覆蓋子類中的方法,並指定更“窄”(即更具體)的返回類型。請參閱stackoverflow.com/questions/14694852 / .... - FeralWhippet 2017年8月9日2:01

15楼
-20
public <X,Y> X nextRow(Y cursor) {
    return (X) getRow(cursor);
}

private <T> Person getRow(T cursor) {
    Cursor c = (Cursor) cursor;
    Person s = null;
    if (!c.moveToNext()) {
        c.close();
    } else {
        String id = c.getString(c.getColumnIndex("id"));
        String name = c.getString(c.getColumnIndex("name"));
        s = new Person();
        s.setId(id);
        s.setName(name);
    }
    return s;
}

You can return any type and receive directly like. Don't need to typecast.

Person p = nextRow(cursor); // cursor is real database cursor.

This is best if you want to customize any other kind of records instead of real cursors.

你說“不需要類型轉換”,但顯然有涉及類型轉換:(光標)光標為例。 - Sami Laine 2016年5月6日17:23

0
votes
answers
9 views
+10

爲什麼foo((&i)++)給出左值需要的錯誤。有沒有相關的

6

我瞭解左值的幾件事數組,但我不明白下面的代碼是如何給出一個錯誤:爲什麼foo((&i)++)給出左值需要的錯誤。有沒有相關的

#include<stdio.h> 

void foo(int *); 

int main() 
{ 
    int i=10; 
    foo((&i)++); 
} 

void foo(int *p) 
{ 
    printf("%d",*p); 
} 

6:13:錯誤:需要左值的遞增操作數 FOO(( & i)++); ^

+3

由於'&i'不是*左值*以及''++操作者需要一個。這大致相當於'&i = &i + 1;',最後一個表達式對你有意義嗎? –

+1

使用變量'i'是一個左值。如果你有像'int * p =&i;'這樣的指針,那麼'p'也是一個左值。但'&我'本身*不是*左值。也許你會對[這個值類別參考]感興趣(http://en.cppreference.com/w/c/language/value_category)?請注意,[非左值表達式列表](http://en.cppreference.com/w/c/language/value_category#Non-lvalue_object_expressions)包含「地址 - 運算符」。 –

+0

可能重複[左值需要作爲增量操作數](https://stackoverflow.com/questions/3364445/lvalue-required-as-increment-operand) – ssharma

沙发
0
2

x ++以下步驟的結果。

1) read the value of x in to register. 
2) increment the value of x 
3) write the incremented value back to x (which means you are changing the value of x by '1') 

但是你正在嘗試做的是(& I)++,這意味着以下。

1) read address of i into register 
2) increment the address by 1 
3) write the incremented value in to address again? How you can change the address? 

如果要將存儲在下一個地址中的整數發送到foo(),則需要按如下方式增加。

int *p = &i + 1; 
foo(p); 

但是,這可能會導致未定義的行爲,因爲你只知道我存儲的值的地址。一旦你增加地址,你會得到下一個地址,它可能包含一些垃圾值。

板凳
0
1

試圖將一元運算符&應用於臨時對象,該臨時對象的計算結果爲表達式(&i)++。您不得將操作員應用於臨時對象。

C標準(6.5.3.2地址和間接運算符):

1 The operand of the unary & operator shall be either a function designator, the result of a [] or unary * operator, or an lvalue that designates an object that is not a bit-field and is not declared with the register storage-class specifier.

+1

「*嘗試將一元運算符'&應用於臨時對象... *」確定? '&'適用於'i'。對我來說,看起來好像你混淆了'&'和'++'。 – alk

0
votes
answers
34 views
+10

如何從PHP中的JAR捕獲返回值並顯示它

1

我有以下JAVA程序已被轉換爲JAR文件並放在與我的PHP文件相同的目錄中。 所以基本上它需要通過PHP傳遞參數,並顯示如何從PHP中的JAR捕獲返回值並顯示它

public class Test { 
    public static void main(String[] args) throws Exception { 
     //Takes the value passed from the PHP 
     String Name = (new String(args[0])).toString(); 
     //This will be treated as Output Parameter which will be returned to PHP 
     System.out.println("Return to PHP"); 

    } 
} 

下面是我的PHP代碼將執行JAR文件和所需的1個參數傳遞給JAR。

<?php 

$arg1 = "My_INPUT_PARAMETER"; 

shell_exec("java -jar TEST.jar $arg1"); 
echo "Done"; 

?> 

我在某處讀到Sysout(System.out.println)中放置的任何內容都將被視爲輸出參數或PHP返回值。 所以在我的情況下,它將是字符串「返回到PHP」。

但我無法獲得PHP的價值並顯示它。

我試着在exec語句中放置一個輸出值,但它不起作用。 我嘗試了下面的代碼,但它拋出我的錯誤。

<?php 

$arg1 = "My_INPUT_PARAMETER"; 
$output = ''; 

shell_exec("java -jar TEST.jar $arg1", $output); 
echo "Done"; 
echo $output; 

?> 

誰能幫助我在這裏,我怎樣才能從PHP得到PHP或輸出參數返回值,並顯示它或我的PHP中使用它,並繼續與其他執行部分。

+0

看看藝術第一個例子在文檔http://php.net/manual/en/function.shell-exec.php。 '$ output = shell_exec(「java -jar TEST.jar $ arg1」);' –

+0

@RolandStarke感謝隊友,它的工作文件。這適用於單個返回值但是,如果JAR文件返回多個值,那我該如何使用它呢? –

沙发
0
0

謝謝@Roland Starke。

所以基本上我們可以用2條語句從PHP運行JAR文件: EXEC和SHELL_EXEC。

EXEC將保存來自JAR文件的所有返回值,我們可以使用它作爲數組並顯示所需的輸出參數。

SHELL_EXEC將保存所有的輸出參數,它將一次顯示全部。

<?php 

$arg1 = "Multi Return"; 

exec("java -jar TEST.jar $arg1",$output); 

echo $output[0]."<br/>"; 

echo $output[1]; 

echo "-------------------------------"; 

$shell_out = shell_exec("java -jar TEST.jar $arg1"); 

echo $shell_out; 

?> 
0
votes
answers
21 views
+10

請解釋一下golang類型是否按值傳遞

1

我試圖製作一個非常簡單的程序來修改數組,但是如果將它們轉換爲類型,會遇到一些有趣的行爲。 https://play.golang.org/p/KC7mqmHuLw看來,如果我有一個數組去傳遞參考,但如果我有一個類型,然後去傳遞值。它是否正確?請解釋一下golang類型是否按值傳遞

我有兩個變量b和c,都是3個整數數組,但c是cT類型,在其他方面它們應該是相同的。我可以將值分配爲b[0]=-1c[0]=-1,但是如果將這些數組作爲參數傳遞給函數,則它們的作用非常不同。

的程序的輸出是:

B之前:[1 2 3]

在C之前:[1 2 3]

* B後:[-1 2 0 ]

* c之後:[-1 2 3]

*什麼? c:[-1 2 0]

我最初的假設是,「在b之後」和「在c之後」應該是相同的。我是在做一些不正確的事情,還是我正確地將類型傳遞給函數的值(即在傳遞給函數之前創建變量的副本)?

package main 

import "fmt" 

type cT [3]int 

func main() { 
    b := []int{1, 2, 3} 
    c := cT{1, 2, 3} 

    fmt.Println("before b:", b) 
    fmt.Println("before c:", c) 

    b[0] = -1 
    c[0] = -1 
    mangleB(b) // ignore return value 
    mangleC(c) // ignore return value 

    fmt.Println("*after b:", b) 
    fmt.Println("*after c:", c) 

    c = mangleC(c)  
    fmt.Println("*what? c:", c)  
} 

func mangleB(row []int) []int { 
    row[2] = 0 
    return row 
} 

func mangleC(row cT) cT{ 
    row[2] = 0 
    return row 
} 
+0

OK,感謝您的幫助!通過提供的信息,我得到了我想要的效果,通過傳遞類型'manglePC(&c)'的引用並將函數更改爲:func manglePC(row * cT){* row} [2] = 0 }' – SammyO

沙发
0
2

The Go Programming Language Specification

Array types

數組是一種單一類型的元素的編號序列,稱爲 元素類型。

Slice types

切片是用於底層 陣列的連續區段的描述符並提供訪問從 數組元素的編號序列。

Calls

在一個函數調用,該函數值和參數在 通常的順序進行評估。評估完成後,呼叫 的參數將按值傳遞給函數,被調用的函數將開始執行 。當函數返回時,函數的返回參數通過值 傳回給調用函數。


type cT [3]int 

b := []int{1, 2, 3} 
c := cT{1, 2, 3} 

我有兩個變量,bc,都是3個整數


不,你不數組!

b切片int與長度(len(b))3和容量(cap(b))3,c是(len(c))3 int一個陣列

在Go中,所有參數都按值傳遞。 b作爲切片描述符傳遞,c作爲數組傳遞。切片描述符是具有切片長度和容量的struct以及指向底層數組的指針。

板凳
0
0

看評論:

func main() { 
    b := []int{1, 2, 3} // slice 
    c := cT{1, 2, 3} // array 

    fmt.Println("before b:", b) 
    fmt.Println("before c:", c) 

    b[0] = -1 
    c[0] = -1 

    // passing in a slice which you can think of as ref to array 
    // pass by value, and it is copy of ref to array 
    mangleB(b) // ignore return value 

    // passing in copy of array (pass by value) 
    // yes full shallow copy of array 
    mangleC(c) // ignore return value 
    // if you ignore return modifications are lost 

    fmt.Println("*after b:", b) 
    fmt.Println("*after c:", c) 

    // return value is modified array 
    c = mangleC(c) 
    // c now copy of array from line 24 

    fmt.Println("*what? c:", c) 
} 

https://play.golang.org/p/OAaCMhc-Ug

0
votes
answers
18 views
+10

嵌套字典鍵和值

-2
mydict = {'Papa': {12: {45: {'AG'}}}} 
mydict['Rocks']['Big'] = 'black' 
>>>print(mydict) 
{'Papa': {Marbles: {Small: {'blue'}}}, {'Rocks': {'Big': {'black'}} 

[evaluate asdf.py] 
Traceback (most recent call last): 
    File "C:/Users/Justin/asdf.py", line 2, in <module> 
    mydict['Rocks']['Big'] = 'black' 
builtins.KeyError: 'Rocks' 

我得到一個關鍵錯誤...如何解決這個問題?請幫忙!嵌套字典鍵和值

+2

您應該顯示產生錯誤的代碼,而實際的錯誤。 –

+0

修正了它!抱歉! – user13123

沙发
0
0

你得到KeyError: 'Rocks'因爲你要添加black針對受RockRock嵌套的關鍵Big還不存在

爲了解決這個問題,你可以加入這一行,而不是當前

mydict['Rocks']={'Big' : {'black'}} 

這將添加{'Big' : {'black'}}的密鑰值Rock而不是您在代碼段中嘗試的子密鑰Big

輸入

print(mydict['Rocks']['Big']) 

嘗試輸出,它將輸出{'black'}

+0

Oo ............... – user13123